【问题标题】:Google App Engine: Is it possible to do a Gql LIKE query?Google App Engine:是否可以进行 Gql LIKE 查询?
【发布时间】:2010-09-08 01:08:36
【问题描述】:

真的很简单。在 SQL 中,如果我想在一个文本字段中搜索几个字符,我可以这样做:

SELECT blah FROM blah WHERE blah LIKE '%text%'

App Engine 的文档没有提到如何实现这一点,但它肯定是一个足够普遍的问题吗?

【问题讨论】:

  • 持续的问题围绕着人们试图使用 GAE 数据存储,就好像它是一个关系/~SQL 数据库一样。通过谷歌引入 GQL,它进一步引导人们从 SQL 系统的角度思考。不过,我知道 Google 正在努力让每个人的过渡变得更加容易,尽管我不确定这是不是正确的方法。

标签: google-app-engine google-cloud-datastore gql


【解决方案1】:

BigTable 是 App Engine 的数据库后端,将扩展到数百万条记录。因此,App Engine 将不允许您执行任何会导致表扫描的查询,因为对于填充良好的表来说性能会很糟糕。

换句话说,每个查询都必须使用索引。这就是为什么您只能进行=>< 查询的原因。 (实际上你也可以使用!=,但是API 使用>< 查询的组合来实现。)这也是开发环境监控你所做的所有查询并自动将任何缺失的索引添加到你的查询的原因。 index.yaml 文件。

没有办法为LIKE 查询建立索引,所以它根本不可用。

关注this Google IO session 以获得更好、更详细的解释。

【讨论】:

    【解决方案2】:

    我遇到了同样的问题,但我在谷歌应用引擎页面上发现了一些东西:

    提示:查询过滤器没有明确的方式来匹配字符串值的一部分,但您可以使用不等式过滤器伪造前缀匹配:

    db.GqlQuery("SELECT * FROM MyModel WHERE prop >= :1 AND prop < :2",
                "abc",
                u"abc" + u"\ufffd")
    

    这将每个 MyModel 实体与以字符 abc 开头的字符串属性 prop 匹配。 unicode 字符串 u"\ufffd" 表示最大可能的 Unicode 字符。当属性值在索引中排序时,落在此范围内的值是所有以给定前缀开头的值。

    http://code.google.com/appengine/docs/python/datastore/queriesandindexes.html

    也许这可以解决问题;)

    【讨论】:

    • +1 值得指出的是,这是区分大小写的。幸运的是,我正在查询的字段中的数据在存储之前已转换为小写。
    【解决方案3】:

    Altough App Engine 不支持 LIKE 查询,请查看属性 ListPropertyStringListProperty。当对这些属性进行相等测试时,测试实际上将应用于所有列表成员,例如,list_property = value 测试该值是否出现在列表中的任何位置。

    有时,此功能可能会用作缺少 LIKE 查询的解决方法。例如,它使simple text search, as described on this post成为可能。

    【讨论】:

    • 帖子不存在了
    【解决方案4】:

    您需要使用search service 执行类似于SQL LIKE 的全文搜索查询。

    Gaelyk 提供特定领域的语言来执行更多user friendly search queries。例如,以下 sn-p 将查找从最新书籍中排序的前十本书,标题包含fern 以及与thriller完全匹配的流派:

    def documents = search.search {
        select all from books
        sort desc by published, SearchApiLimits.MINIMUM_DATE_VALUE
        where title =~ 'fern'
        and genre =  'thriller'
        limit 10
    }
    

    Like 写成 Groovy 的匹配运算符 =~。 也支持distance(geopoint(lat, lon), location)等功能。

    【讨论】:

      【解决方案5】:

      App 引擎在 1.7.0 版中推出了通用的full text search service,支持数据存储。

      announcement中的详细信息。

      更多关于如何使用的信息:https://cloud.google.com/appengine/training/fts_intro/lesson2

      【讨论】:

        【解决方案6】:

        看看 Objectify here ,它就像一个数据存储访问 API。这个问题有一个FAQ,这里是答案

        如何进行类似查询 (LIKE "foo%")
        如果在存储和搜索时颠倒顺序,您可以执行 startWith 或 endWith 之类的操作。您使用所需的起始值和刚好高于所需值的值进行范围查询。

        String start = "foo";
            ... = ofy.query(MyEntity.class).filter("field >=", start).filter("field <", start + "\uFFFD");
        

        【讨论】:

        • 它将搜索“开始于”而不是“包含”。
        【解决方案7】:

        请按这里: init.py#354">http://code.google.com/p/googleappengine/source/browse/trunk/python/google/appengine/ext/search/init.py#354

        有效!

        class Article(search.SearchableModel):
            text = db.TextProperty()
            ...
        
          article = Article(text=...)
          article.save()
        
        To search the full text index, use the SearchableModel.all() method to get an
        instance of SearchableModel.Query, which subclasses db.Query. Use its search()
        method to provide a search query, in addition to any other filters or sort
        orders, e.g.:
        
          query = article.all().search('a search query').filter(...).order(...)
        

        【讨论】:

          【解决方案8】:

          我使用 GAE Datastore 低级 Java API 对此进行了测试。我和完美的工作

              Query q = new Query(Directorio.class.getSimpleName());
          
              Filter filterNombreGreater = new FilterPredicate("nombre", FilterOperator.GREATER_THAN_OR_EQUAL, query);
              Filter filterNombreLess = new FilterPredicate("nombre", FilterOperator.LESS_THAN, query+"\uFFFD");
              Filter filterNombre =  CompositeFilterOperator.and(filterNombreGreater, filterNombreLess);
          
              q.setFilter(filter);
          

          【讨论】:

          • 这适用于前缀,但如果我想从字符串的末尾匹配呢?例如 - 我想在 sdfdsabc 中搜索 abc,那么它应该返回 sdfdsabc
          【解决方案9】:

          一般来说,即使这是一篇旧文章,产生“LIKE”或“ILIKE”的一种方法是从“>=”查询中收集所有结果,然后在 python(或 Java)中循环结果以获取元素包含您要查找的内容。

          假设您要过滤给定 q='luigi' 的用户

          users = []
          qry = self.user_model.query(ndb.OR(self.user_model.name >= q.lower(),self.user_model.email >= q.lower(),self.user_model.username >= q.lower()))
          
          for _qry in qry:
           if q.lower() in _qry.name.lower() or q.lower() in _qry.email.lower() or q.lower() in _qry.username.lower():
                users.append(_qry)
          

          【讨论】:

            【解决方案10】:

            不可能在数据存储应用程序引擎上进行 LIKE 搜索,如果您需要在字符串中搜索单词,那么创建 Arraylist 将如何解决问题。

            @Index
                public ArrayList<String> searchName;
            

            然后使用objectify在索引中搜索。

            List<Profiles> list1 = ofy().load().type(Profiles.class).filter("searchName =",search).list();
            

            这将为您提供一个列表,其中包含您在搜索中所做的世界的所有项目

            【讨论】:

              【解决方案11】:

              如果LIKE '%text%' 总是与一个或几个单词相比较(想想排列),并且您的数据变化缓慢(缓慢意味着创建和更新索引的成本和性能都不是太高),那么关系索引实体 (RIE) 可能是答案。

              是的,您必须构建额外的数据存储实体并适当地填充它。是的,您必须考虑一些限制(其中一个是 GAE 数据存储中列表属性的长度限制为 5000)。但由此产生的搜索速度快如闪电。

              有关详细信息,请参阅我的 RIE with Java and OjbectifyRIE with Python 帖子。

              【讨论】:

                【解决方案12】:

                “Like”通常用作文本搜索的穷人替代品。对于文本搜索,可以使用Whoosh-AppEngine

                【讨论】:

                  猜你喜欢
                  • 2011-04-06
                  • 1970-01-01
                  • 2013-10-13
                  • 2012-07-23
                  • 2015-12-22
                  • 2012-07-12
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多