Google app engine 查询重复属性以开头

Google app engine 查询重复属性以开头,google-app-engine,google-cloud-datastore,app-engine-ndb,Google App Engine,Google Cloud Datastore,App Engine Ndb,假设我有一个电影数据库,你可以通过标题搜索 我有一个电影模型,看起来像下面的(简化) queryName只是Movie.name中单词的小写列表。parent\u key()基本上只是用于查询 如果我在搜索电影《森林阿甘》,我希望它能在以下搜索词中显示出来(还有更多,这些只是示例) “fo”-“forest”以“fo”开头 “gu”-“gump”以“gu”开头 “gu fo”-“forest”以“fo”开头,“gump”以“gu”开头 我可以通过类似于下面的查询轻松获得前两个 movies =

假设我有一个电影数据库,你可以通过标题搜索

我有一个
电影
模型,看起来像下面的(简化)

queryName
只是
Movie.name
中单词的小写列表。
parent\u key()
基本上只是用于查询

如果我在搜索电影《森林阿甘》,我希望它能在以下搜索词中显示出来(还有更多,这些只是示例)

  • “fo”-“forest”以“fo”开头
  • “gu”-“gump”以“gu”开头
  • “gu fo”-“forest”以“fo”开头,“gump”以“gu”开头
  • 我可以通过类似于下面的查询轻松获得前两个

    movies = Movie\
        .query(ancestor=Movie.parent_key())\
        .filter(Movie.queryName >= x)\
        .filter(Movie.queryName < x + u'\ufffd')\
        .feth(10)
    
    更新:

    我目前的解决办法是

    class MovieSearchHandler(BaseHandler):
        def get(self):
            q = self.request.get('q')
    
            if q:
                q = q.replace('&', '&amp;').lower().split()
                movieFilter, reducable = self.create_filter(*q)
    
                if movieFilter:
                    movies = Movie\
                        .query(ancestor=Movie.parent_key())\
                        .filter(movieFilter)\
                        .fetch(None if reducable else 10)
    
                    if reducable:
                        movies = self.reduce(movies, q)
    
                    return self.write_json([{'id': m.movieId, 'name': m.name} for m in movies])
    
            return self.write_json([])
    
        def create_filter(self, *args):
            if args:
                if len(args) == 1:
                    prefix = args[0]
                    return ndb.AND(Movie.queryName >= prefix, Movie.queryName < prefix + u'\ufffd'), False
    
                ands = [ndb.AND(Movie.queryName >= prefix, Movie.queryName < prefix + u'\ufffd')
                        for prefix in args]
    
                return ndb.OR(*ands), True
    
            return None, False
    
        def reduce(self, movies, terms):
            reducedMovies = []
    
            for m in movies:
                if len(reducedMovies) >= 10:
                    return reducedMovies
                if all(any(n.startswith(t) for n in m.queryName) for t in terms):
                    reducedMovies.append(m)
    
            return reducedMovies
    
    class MovieSearchHandler(BaseHandler):
    def get(自我):
    q=self.request.get('q')
    如果q:
    q=q.replace('&','&;').lower().split()
    电影过滤器,可还原=自创建过滤器(*q)
    如果是电影过滤器:
    电影\
    .query(祖先=Movie.parent\u key())\
    .过滤器(电影过滤器)\
    .fetch(如果可还原,则为无,否则为10)
    如果可还原:
    电影=自我减少(电影,q)
    返回self.write_json([{'id':m.movieId,'name':m.name}表示电影中的m])
    返回self.write_json([])
    def create_过滤器(自身,*参数):
    如果参数为:
    如果len(args)==1:
    前缀=args[0]
    返回ndb.AND(Movie.queryName>=前缀,Movie.queryName=前缀,Movie.queryName=10:
    返回还原移动
    如果全部(任何(n.startswith(t)表示m.queryName中的n)表示t,则以术语表示:
    reducedMovies.append(m)
    返回还原移动
    
    不过还是在找更好的


    谢谢

    你有没有考虑过使用全文搜索,或者“嗖”的一声,我不认为你能从直接的数据存储中得到你想要的。是的,我想说的是,使用全文搜索可以很容易地做到,但我的问题已经太长了。然而,我不想满足于此,因为我觉得这真的损害了可用性。谢谢你。
    movies = Movie\
        .query(ancestor=Movie.parent_key())\
        .filter(Movie.queryName >= 'fo')\
        .filter(Movie.queryName < 'fo' + u'\ufffd')\
        .filter(Movie.queryName >= 'gu')\
        .filter(Movie.queryName < 'gu' + u'\ufffd')\
        .feth(10)
    
    class MovieSearchHandler(BaseHandler):
        def get(self):
            q = self.request.get('q')
    
            if q:
                q = q.replace('&', '&amp;').lower()
                filters = self.create_filter(*q.split())
    
                if filters:
                    movies = Movie\
                        .query(ancestor=Movie.parent_key())\
                        .filter(*filters)\
                        .fetch(10)
    
                    return self.write_json([{'id': m.movieId, 'name': m.name} for m in movies])
    
            return self.write_json([])
    
        def create_filter(self, *args):
            filters = []
    
            if args:
                for prefix in args:
                    filters.append(Movie.queryName >= prefix)
                    filters.append(Movie.queryName < prefix + u'\ufffd')
    
            return filters
    
    class MovieSearchHandler(BaseHandler):
        def get(self):
            q = self.request.get('q')
    
            if q:
                q = q.replace('&', '&amp;').lower().split()
                movieFilter, reducable = self.create_filter(*q)
    
                if movieFilter:
                    movies = Movie\
                        .query(ancestor=Movie.parent_key())\
                        .filter(movieFilter)\
                        .fetch(None if reducable else 10)
    
                    if reducable:
                        movies = self.reduce(movies, q)
    
                    return self.write_json([{'id': m.movieId, 'name': m.name} for m in movies])
    
            return self.write_json([])
    
        def create_filter(self, *args):
            if args:
                if len(args) == 1:
                    prefix = args[0]
                    return ndb.AND(Movie.queryName >= prefix, Movie.queryName < prefix + u'\ufffd'), False
    
                ands = [ndb.AND(Movie.queryName >= prefix, Movie.queryName < prefix + u'\ufffd')
                        for prefix in args]
    
                return ndb.OR(*ands), True
    
            return None, False
    
        def reduce(self, movies, terms):
            reducedMovies = []
    
            for m in movies:
                if len(reducedMovies) >= 10:
                    return reducedMovies
                if all(any(n.startswith(t) for n in m.queryName) for t in terms):
                    reducedMovies.append(m)
    
            return reducedMovies