App Engine数据存储区不支持运算符OR

时间:2009-05-31 00:45:56

标签: java google-app-engine google-cloud-datastore jdoql

我正在尝试查询google数据存储区(例如pm - > persistanceManager):

String filters = "(  field == 'value' ||  field == 'anotherValue' )";
Query query = pm.newQuery(myType.class, filters);

当我执行时 - 我回来了: App Engine数据存储区不支持operator OR

人们在此类查询中遇到的最佳方法是什么?

任何帮助表示赞赏!

8 个答案:

答案 0 :(得分:10)

执行多个查询。与所有其他数据库一样,数据存储区无法有效地执行析取。与其他数据库不同,它向用户暴露了这一难题,明确表示您正在做的事情并不高效。您唯一的解决方案是执行多个查询 - 每个查询一个或 - 并将它们组合在一起。

答案 1 :(得分:4)

我不知道GAE的JDO和JPA实现是否支持这一点,但是使用低级API,您可以在一个查询中使用运算符IN。

Query query = new Query("Issue");
List<String> list = Arrays.asList("NEW", "OPEN", "ACCEPTED");
query.addFilter("status", FilterOperator.IN, list);

DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
PreparedQuery preparedQuery = datastore.prepare(query);
for (Entity entity : preparedQuery.asIterable()) {
    // should iterate over 'NEW', 'OPEN' and 'ACCEPTED' issues
}

答案 2 :(得分:2)

根据Google App Engine - Queries and Indexes

  

查询过滤器

     

过滤器指定字段名称,   运算符和值。价值   必须由应用程序提供;这不可以   指另一个属性,或者是   以其他方式计算   属性。运营商可以是任何一个   以下内容:< <= == >= >

     
    

注意: Java数据存储区接口不支持!=和     IN过滤器     在中实现的运算符     Python数据存储区接口。 (在里面     Python接口,这些运算符都是     在客户端实现     库作为多个数据存储区     查询;它们不是特征     数据存储本身。)

  
     

过滤器的主题可以是任何   对象字段,包括主要字段   密钥和实体组父级(请参阅   Transactions)。

     

实体必须匹配所有过滤器   结果。在JDOQL字符串语法中,   指定了多个过滤器   由&&(逻辑“和”)分隔。   过滤器的其他逻辑组合   (逻辑“或”,“不是”)不是   支撑。

     

由于App Engine的方式   数据存储区执行查询,单个   查询不能使用不等式过滤器   (< <= >= >)不止一个   属性。多个不等式过滤器   在同一个属性上(例如查询   允许一系列值)。   请参阅Restrictions on Queries

基本上,您要么必须重新构建数据,以便您可以通过一个条件或多个“和”条件找到您要查找的内容,或者您​​将不得不通过两个条件检索数据(或者更多)查询并在代码中过滤/组合它。

答案 3 :(得分:1)

抱歉,我迟到了。我今天刚遇到你的问题。

“模拟”“IN”和“OR”行为的另一种方法是使用“低级”数据存储区API。 DatastoreService支持get()方法,该方法接受Keys的集合并返回与传入的Keys匹配的所有实体的Map。它是一个接口,但是有一个方便的DatastoreServiceFactory可以分配一个现成的实例。

不幸的是,谷歌决定他们不想推广这种低级API方法,而是希望开发人员使用JDO或JPA,因此除了JavaDocs以及您在Google上找到的任何代码示例时,都没有可用的文档。 “DatastoreService”。

TL

答案 4 :(得分:1)

最新新闻..至少我刚刚收到它。当我下载最新的GAE Java SDK时,我在发行说明中注意到“问题29:暴露批量获取”在最新版本(v1.2.1)中得到修复。基本上似乎我们(我正在寻找相同的支持)可能有基于JDO的替代方案,而不是必须下载到“低级”数据存储API。我刚刚下载了最新的Java GAE SDK,所以我还没有机会测试任何东西,但我想尽快给你一个提醒。在我有机会确认这个“修复”后,我会发布更多信息。

如果我通过重新发布我的评论作为答案来破坏StackOverflow礼仪,请接受我的道歉,但我决定这样做有两个原因。首先是因为,即使我再次解决同一问题,恕我直言这个新信息似乎提供了一个完全不同的问题“答案”。其次,我担心在您花费大量时间研究我提供的第一个答案之前,评论表可能不会引起您的注意。

下次我会在演戏前仔细考虑。

TL

答案 5 :(得分:0)

简化必须“自己动手”的一种方法可能是使用参数化查询:

   Query query = pm.newQuery(mytype.class);
   query.setFilter("field == autoParam");
   query.declareParameters("String autoParam");

   List<String> params = myListOfThingsFieldCanBeEqualTo;

   Set merged = new HashSet();
   for (String f : params) {
     merged.addAll(q.execute(f));
   }

答案 6 :(得分:0)

与cletus的回答相反, OR-ing工作,无论如何都要在更新版本的App Engine中使用。

事实上,我发现OR-ing在App Engine 1.3.0中不起作用,但根据Google App Engine - Queries and Indexes(在他的回答中提到的源代码),

  

实体必须将所有过滤器都匹配为结果。在JDOQL字符串语法中,您可以使用||分隔多个过滤器(逻辑“或”)和&amp;&amp; (逻辑“和”),但请记住||只有当它分隔的过滤器都具有相同的字段名称时才能使用它。换句话说,||只有在它分离的过滤器可以组合成一个contains()过滤器的情况下才是合法的。

我认为自从他的答案(以及我上次更新我的App Engine以来),App Engine必须已经升级了。

将App Engine更新为1.3.4,OR-ing正常工作!虽然有限制。

感谢cletus:)

答案 7 :(得分:0)

您可以使用contains方法

String filters = "( :values.contains(field) )";
Query query = pm.newQuery(myType.class, filters);