Yhzhtk's Blog

(热爱技术,高效Code)     归档  标签  源码  关于 


阿里云开放云搜索初探

2013-07-02    云搜索  python 


    前几天申请了阿里云开放云搜索(Aliyun OpenSearch)的邀请码,今早通过收到通过验证了,于是准备试试云搜索

    阿里云搜索使用很简单,和Lucene一样,包括索引文档字段几个概念。每个索引可以当成数据库的一个数据库,一条文档当成数据库的一条记录,一个字段就是数据库的一个字段。

    目前支持四种形式的搜索模板,资讯类,小说类,应用类和社区类。模板在这儿就是规定好了索引的字段,也可以自定义。详细介绍

    我想测试一下,就把自己的博客写的这十几篇POST发上去建立索引吧,使用了资讯类的模板。

模板字段如下:
字段名 类型 字段说明 独立检索 可检索 可排序 可筛选
id STRING 文档标识(必选)      
title TEXT 资讯标题    
body TEXT 资讯内容      
type_id UINT16 类型,如财经      
cat_id UINT16 组别,支持多个,如"cat_id":[12, 13]、"cat_id":["12", "13"],具体请参加模版数据类型说明      
url STRING 展示url        
author TEXT 作者    
thumbnail STRING 缩略图        
source TEXT 新闻来源      
create_timestamp UINT32 创建时间    
update_timestamp UINT32 更新时间    
hit_num UINT32 点击数    
focus_count UINT32 关注数    
grade UINT32 读者评分    
comment_count UINT32 评论数    
boost INT8 站长自定义加分项    
integer_1 UINT32 保留字段,站长自定义    
integer_2 UINT32 保留字段,站长自定义    
integer_3 UINT32 保留字段,站长自定义    
tag TAG 标签      
display_text STRING 站长自定义展示字段        

提供的需要上传的JSON格式示例:

[
    {
        "fields": {
            "body": "广大中小企业都有各种结构化的数据需要进行检索,目前一般采用数据库本身提供的搜索功能或者利用open source的搜索软件搭建", 
            "display_text": "open search", 
            "hit_num": "88888", 
            "update_timestamp": "1345448016", 
            "type_id": "1", 
            "url": "http://www.aliyun.com", 
            "cat_id": [1,2], 
            "author": "阿里云", 
            "grade": "10", 
            "comment_count": "1234", 
            "tag": {"搜索":10,"阿里云":2,"云搜索":5,"开放搜索":8}, 
            "source": "阿里云云搜索", 
            "focus_count": "8888", 
            "title": "阿里云隆重推出开放搜索", 
            "boost": "1", 
            "id": "id_1", 
            "integer_1": "100", 
            "create_timestamp": "1345448016"
        }, 
        "cmd": "ADD"
    }, ...
]

    其中很多字段用不上,可以忽略。我的博客都是在jekyll中的post类型,需要把所有的post转为JSON格式。我写了一个Python,来处理_post文件夹下面的所有文章,最后导出Json

#coding=utf-8
'''
将jekyll中_post目录下的文章到处json格式,用于阿里云搜索
@author: gudaihui
'''

import os
import re
import json
import time

def object2dict(obj):
    '''使用内置json转换时,需要将对象转为dict'''
    #convert object to a dict
    d = {}
    d.update(obj.__dict__)
    return d

class PostInfo():
    '''存储一条博客的所有字段类'''
    def __init__(self, title, tags, content, rooturl, f):
        self.title = title
        self.tag = {}
        #标签有一个权重,默认都为1
        for t in tags.split(","):
            self.tag[t.strip()] = 1
        self.body = content
        self.id = f.replace("-", "").replace(".html", "")
        self.display_text = "open search"
        self.hit_num = "88888"
        #处理日期和URL
        t = re.match('\\d{4}-\\d{2}-\\d{2}', f).group()
        self.url = rooturl + f.replace(t + "-", (t + "-").replace("-", "/"))
        self.update_timestamp = "%d" % time.mktime(time.strptime(t,'%Y-%m-%d'))
        self.create_timestamp = "%d" % time.mktime(time.strptime(t,'%Y-%m-%d'))
        self.type_id = "1"
        self.cat_id= [1,2]
        self.author="yhzhtk"
        self.grade="10"
        self.source="yhzhtk"
        self.boost = "1"

    
def getPostInfo(path, rooturl="http://yhzhtk.info/"):
    '''从文件中读取所有的POST返回PostInfo信息'''
    os.chdir(path)
    posts = [[open(f, "r").read(), f]
             for f in os.listdir(path) if f.endswith(".html")]
    pattern = re.compile(r"---\nlayout: post\ntitle: ([^\n]*)\ntags: \[([^\]]*)\]\n---\n(.*)", re.DOTALL)
    infos = []
    for post, f in posts:
        match = pattern.match(post)
        if match:
            title = match.group(1)
            tags =  match.group(2)
            content = match.group(3)
            content = re.sub("<[^>]*>","",content)
            content = re.sub("{%[^%]*%}","",content)
            content = content.replace("\n", "")
            infos.append(PostInfo(title, tags, content, rooturl, f))
    return infos

def genPostJson(infos):
    '''将PostInfo处理得到最后的Json'''
    jsonstr = ""
    for info in infos:
        temp = json.dumps(info, ensure_ascii=False, default=object2dict)
        temp = '''{"fields":''' + temp + ''', "cmd": "ADD"}'''
        jsonstr += "," + temp
    if json:
        jsonstr = jsonstr[1:]
    jsonstr = "[" + jsonstr + "]"
    print jsonstr

    
if __name__ == '__main__':
    '''开始执行'''
    path = r"C:\Documents and Settings\yicha\blog\_posts"
    infos = getPostInfo(path)
    genPostJson(infos);

    所有的json是直接输出了,也可以输出到一个文件中。然后将文件上传到刚才新建的索引中。刷新,看到文档条数不为0,就可以点击搜索测试了,如果数量仍为0,可以查看错误日志,里面写明了错误的文档和错误原因。最后,可以通过给的API把搜索功能添加到你的产品中。

    搜索的效率问题现在还没法知道,因为文档数比较少。等有机会可以应用到实际中测测。





Load Disqus comments, wait a moment..

©2013 首页   关于     View me on GitHub Powered by Jekyll & Bootstrap 知识共享许可协议