试用GAE数据库的全文搜索功能
2009 5 25 11:09 AM 2290次查看
分类:Google App Engine 标签:Google App Engine, Python
喜欢看源码的可以去看google_appengine\google\appengine\ext\search\__init__.py,或者去Google Code。
不过试用过后,发现隐藏起来(无文档)也是应该的,因为还处于开发阶段,缺陷太多了。
其中最重要的一点:不支持ASCII码以外的字符(这点就足以让我放弃了,不支持中文就没什么能搜的了)。
嘛,还是把用法写出来吧,毕竟还是有人有英文搜索的需求。
首先要注意几点:
- 索引只针对单词(即用空格或标点符号隔开的英文),不能搜索单词的一部分(例如无法通过搜索'hell'来找到'hello')。
- 搜索的最少字数为3,这个是用_FULL_TEXT_MIN_LENGTH定义的。
- 部分常用单词不编入索引(例如'a'),这个是用_FULL_TEXT_STOP_WORDS定义的。
- 索引的单词都调用了lower,所以是不区分大小写的。
- 索引会作用于所有的string和text属性,搜索时不能只指定其中的一个,且属性指定indexed=False时仍会被索引。
- 由于每个单词都要索引,所以索引空间会占用很多,且性能也比一般的要低(即CPU时间会长些)。
- 搜索条件可以有多个,且允许与filter、sort等搭配,搜索限制上类似于IN操作符(即可以与不等于操作符搭配)。
接着看用法:
模型的定义不再使用db.Model,而是使用google.appengine.ext.search的search.SearchableModel,它是db.Model的子类。
数据的存储及删除操作完全与db.Model相同,因为是直接继承自db.Model的。
搜索时增加了一个search方法,将需要搜索的字符填入即可(前面已说过,不支持中文,不区分大小写,忽略常见词和3个字符以下的词)。
如果需要搜索多个词,用空格分隔各个单词即可,或者使用2次search方法。这2种方法在大部分情况下相同,但如果搜索的单词包含被忽略词(常见词和3个字符以下的词),前者会忽略不符合的部分,后者则会忽略整个search条件。即搜索'hello all'(all是常见词),可以找到包含'hello'的实体,但搜索'hello'和'all'则会忽略search条件,搜索所有实体。
索引的定义使用__searchable_text_index,这个是用_FULL_TEXT_INDEX_PROPERTY定义的。
然后给个例子:
# -*- coding: utf-8 -*-
import wsgiref.handlers
from google.appengine.ext import webapp
from google.appengine.ext import db
from google.appengine.ext import search
class Card(search.SearchableModel):
id = db.IntegerProperty()
name = db.StringProperty()
description = db.TextProperty()
class AddHandler(webapp.RequestHandler):
def get(self):
db.put([
Card(id=1172, name='Obelisk the Tormentor', description=u'咒文●其到来之时,灼热之疾风必吹荒大地,生者必成尸骸'),
Card(id=1116, name='Slifer the Sky Dragon', description=u'咒文●天空雷鸣混沌之时,集连锁中之远古魔导书,其力可至无限!'),
Card(id=1177, name='The Winged Dragon of Ra', description=u'咒文●精灵歌唱,亘古之力司万物!其命,其魂,以至其骸。')
])
class DelHandler(webapp.RequestHandler):
def get(self):
db.delete(Card.all().order('id').fetch(500))
class MainHandler(webapp.RequestHandler):
def get(self):
cards = Card.all().search('dragon').fetch(1000)
for card in cards:
self.response.out.write(card.description + '<br />')
def main():
application = webapp.WSGIApplication([('/', MainHandler),
('/add', AddHandler),
('/del', DelHandler)])
wsgiref.handlers.CGIHandler().run(application)
if __name__ == '__main__':
main()
向下滚动可载入更多评论,或者点这里禁止自动加载。