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