在GAE中为SearchableModel指定索引属性集

标签:Google App Engine, Python

几个月前就介绍过这个隐藏的API,但由于不太好用,所以放弃了。
昨天Google更新了这个API,可以自定义索引的属性集,可以定义多条索引,可以指定搜索时使用的索引,算是弥补了一大不足。(之前强制索引所有字符串类型,浪费磁盘空间且降低性能。)

自定义索引集实际上很简单,自定义一个名为SearchableProperties的类方法,返回一个需要索引的属性的2维列表即可,例如:
@classmethod
def SearchableProperties(cls):
  return [['book', 'author'], ['book'], search.ALL_PROPERTIES]
其中search.ALL_PROPERTIES是表示索引所有属性。如果没有覆盖SearchableProperties,则默认为search.ALL_PROPERTIES。

搜索时则需要指定使用的索引,方法同样很简单,用properties指定即可,例如:
Article.all().search('Lem', properties=['book', 'author'])
这里用的是['book', 'author']这个索引。(在index.yaml中表示为__searchable_text_index_book_author)
假如省略properties参数,则会用search.ALL_PROPERTIES来做索引。而如果这个索引不存在,则会抛出异常。

最后给个自己写的例子:
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
from google.appengine.ext import search

def unquote(string):
    from urllib import unquote
    return unicode(unquote(string), 'utf8', 'ignore')

class TestModel(search.SearchableModel):
    title = db.StringProperty()
    text = db.TextProperty()
    comment = db.StringProperty(indexed=False)
    rating = db.RatingProperty()
    
    def toString(self):
        return 'title:%s\ntext:%s\ncomment:%s\nrating:%d\n' % (self.title, self.text, self.comment, self.rating)
    
    @classmethod
    def SearchableProperties(cls):
        return [['title', 'text']]
    
class Add(webapp.RequestHandler):
    def get(self, title, text, comment, rating):
        TestModel(title=unquote(title), text=unquote(text), comment=unquote(comment), rating=int(rating)).save()
    
class Search(webapp.RequestHandler):
    def get(self, words, rating):
        all = TestModel.all()
        entities = all.search(unquote(words), properties=['title', 'text']).filter('rating >= ', int(rating)).order('-rating').fetch(1000)
        self.response.headers['Content-Type'] = 'text/plain; charset=utf-8'
        for entity in entities:
            self.response.out.write(entity.toString() + '\n')
        
class MainPage(webapp.RequestHandler):
    def get(self):
        entities = TestModel.all().order('-rating').fetch(1000)
        self.response.headers['Content-Type'] = 'text/plain; charset=utf-8'
        for entity in entities:
            self.response.out.write(entity.toString() + '\n')


application = webapp.WSGIApplication([('/', MainPage),
                                      (r'/add/(.+)/(.+)/(.*)/(\d{1,2})', Add),
                                      (r'/search/(.+)/(\d{1,2})', Search)], debug=True)


def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()

0条评论 你不来一发么↓

    想说点什么呢?