GAE 已支持中文全文搜索
2012 5 9 05:25 PM 2827次查看
分类:Google App Engine 标签:Google App Engine
我无聊地试了下,发现支持中文,于是便分享一下。
首先要说明的是,这个全文搜索功能并不是 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…
向下滚动可载入更多评论,或者点这里禁止自动加载。