原文转自:http://yhzhtk.info/2013/07/02/1-aliyun-opensearch.html
前几天申请了阿里云开放云搜索(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把搜索功能添加到你的产品中。
搜索的效率问题现在还没法知道,因为文档数比较少。等有机会可以应用到实际中测测。