GAE 已支持中文全文搜索

标签:Google App Engine

今天,Google App Engine Full Text Search Team 发布了一篇《Looking for search? Find it on Google App Engine》,宣告 GAE 上的全文搜索功能已进入实验阶段。
我无聊地试了下,发现支持中文,于是便分享一下。

首先要说明的是,这个全文搜索功能并不是 Datastore 内建的功能,而是一个新的 Search API
优点就是你可以和 Blobstore、Google Storage 等其他服务集成;缺点就是用起来不够方便,需要手动同步 Datastore 和 Search API 的索引。
还需要提醒的是它只能用于 High Replication Datastore 的应用。

接下来就来试试它吧。
它的主要流程是创建文档,把文档添加到索引,然后用索引来搜索。

于是看看创建文档,我在网上找了两条新闻,就用它们来举例:
from google.appengine.api import search

news1 = search.Document(
	doc_id='1', # 可省略
	fields=[
		search.TextField(name='title', value=u'英科学家称全球变暖乃恐龙放屁或打嗝所致'),
		search.HtmlField(name='content', value=u'核心提示:到底是什么导致全球变暖?英国科学家们给出了一个“匪夷所思”的答案:生活在中生代的食草类恐龙排出大量甲烷气体,是全球变暖的重要因素。这一研究结果于近期发表在《当代生物学》杂志上。')
	],
	language='zh' # 默认是 'en',但不会影响搜索结果
)

news2 = search.Document(
	doc_id='2',
	fields=[
		search.TextField(name='title', value=u'媒体调查称中国内地自来水合格率仅50%'),
		search.HtmlField(name='content', value=u'核心提示:据媒体调查称,2009年住建部曾对全国城市饮用水水质状况做普查,但至今未公布数据结果。多位业内人士称,此次检测结果实际合格率仅50%左右。调查显示全国城市供水管网质量普遍低劣,不符国标的灰口铸铁管占一半。目前,北京上海等大城市饮用水仍无法直饮。')
	],
	language='zh'
)

然后把它添加到索引里:
index = search.Index(name='news', consistency=search.Index.GLOBALLY_CONSISTENT)
index.add(news1)
index.add(news2)
索引有 PER_DOCUMENT_CONSISTENT 和 GLOBALLY_CONSISTENT 这两种一致性。前者在查询时可能返回过时的结果,而后者会等待所有更新完成后,才会返回结果。把文档添加到索引可能有几秒钟延迟,如果使用 PER_DOCUMENT_CONSISTENT 的话,也许不能立即查询到它;但 GLOBALLY_CONSISTENT 也有个缺点:每秒大约只能处理一次写操作,因此不能用于高并发的情况。
执行完这步的时候,文档(两篇新闻)就被永久存储了,你可以在以后的任何时候查询,而无需重新添加文档。

现在来试试查询:
>>> print index.search('提示') # 不是 unicode 也能查
search.SearchResults(results='[search.ScoredDocument(doc_id='2', fields='[search.TextField(name='title', value='媒体调查称中国内地自来水合格率仅50%'), search.HtmlField(name='content', value='核心提示:据媒体调查称,2009年住建部曾对全国城市饮用水水质状况做普查,但至今未公布数据结果。多位业内人士称,此次检测结果实际合格率仅50%左右。调查显示全国城市供水管网质量普遍低劣,不符国标的灰口铸铁管占一半。目前,北京上海等大城市饮用水仍无法直饮。')]', language='zh', order_id='42713963'), search.ScoredDocument(doc_id='1', fields='[search.TextField(name='title', value='英科学家称全球变暖乃恐龙放屁或打嗝所致'), search.HtmlField(name='content', value='核心提示:到底是什么导致全球变暖?英国科学家们给出了一个“匪夷所思”的答案:生活在中生代的食草类恐龙排出大量甲烷气体,是全球变暖的重要因素。这一研究结果于近期发表在《当代生物学》杂志上。')]', language='zh', order_id='42713963')]', number_found='2')

>>> results = index.search(u'匪夷所思')
>>> if results.number_found:
... 	print results.results
[search.ScoredDocument(doc_id='1', fields='[search.TextField(name='title', value='英科学家称全球变暖乃恐龙放屁或打嗝所致'), search.HtmlField(name='content', value='核心提示:到底是什么导致全球变暖?英国科学家们给出了一个“匪夷所思”的答案:生活在中生代的食草类恐龙排出大量甲烷气体,是全球变暖的重要因素。这一研究结果于近期发表在《当代生物学》杂志上。')]', language='zh', order_id='42713963')]

>>> print index.search(u'title:匪夷所思').number_found
0
>>> print index.search(u'content:匪夷所思').number_found
1
>>> print index.search(u'匪').number_found # 单个汉字不索引
0
>>> print index.search(u'研究结果 恐龙放屁').number_found # 用空格分隔关键字,可以处于多个字段中
1
>>> print index.search(u'变暖 OR 饮用水 NOT 2009年').number_found # 支持 AND、OR 和 NOT 等操作符
1

最后来试试按照关键字的出现次数来排序:
news1 = search.Document(
	doc_id='1',
	fields=[
		search.TextField(name='title', value=u'我晕' * 10)
	],
	language='zh'
)

news2 = search.Document(
	doc_id='2',
	fields=[
		search.TextField(name='title', value=u'我晕' * 5)
	],
	language='zh'
)

news3 = search.Document(
	doc_id='3',
	fields=[
		search.TextField(name='title', value=u'我晕' * 15)
	],
	language='zh'
)

index.add([news1, news2, news3])

print index.search(
	search.Query(
		u'我晕',
		options=search.QueryOptions(
			sort_options=search.SortOptions(
				expressions=[search.SortExpression(expression='title', default_value='')]
			),
			ids_only=True
		)
	)
)
结果:
search.SearchResults(results='[search.ScoredDocument(doc_id='3', order_id='0'), search.ScoredDocument(doc_id='1', order_id='0'), search.ScoredDocument(doc_id='2', order_id='0')]', number_found='3')

暂时就演示这么多吧,其他的还是自己看文档吧。
看来我得改进下 Doodle 的搜索功能了,不知道免费配额够不够用,更头疼的是移植到 HRD…

13条评论 你不来一发么↓ 顺序排列 倒序排列

    向下滚动可载入更多评论,或者点这里禁止自动加载

    想说点什么呢?