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

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

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

当我执行时 – 我回来了: App Engine数据存储区不支持运算符OR

对于这类查询,人们体验的最佳方法是什么?

任何帮助赞赏!

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

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

 Query query = new Query("Issue"); List 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 } 

根据Google App Engine – 查询和索引 :

查询filter

filter指定字段名称,运算符和值。 该值必须由应用程序提供; 它不能引用其他财产,也不能根据其他财产计算。 运算符可以是以下任何一种: < <= == >= >

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

filter的主题可以是任何对象字段,包括主键和实体组父对象(请参阅事务 )。

实体必须将所有filter匹配为结果。 在JDOQL字符串语法中,指定了多个filter,用&& (逻辑“和”)分隔。 不支持filter的其他逻辑组合(逻辑“或”,“非”)。

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

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

对不起,我迟到了。我今天刚碰到你的问题。

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

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

TL

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

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

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

TL

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

  Query query = pm.newQuery(mytype.class); query.setFilter("field == autoParam"); query.declareParameters("String autoParam"); List params = myListOfThingsFieldCanBeEqualTo; Set merged = new HashSet(); for (String f : params) { merged.addAll(q.execute(f)); } 

与cletus的回答相反, OR-ing无论如何都适用于更新版本的App Engine。

事实上,我发现OR-ing在我的App Engine 1.3.0中没有工作,但根据Google App Engine – 查询和索引 (在他的回答中提到的相同来源cletus),

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

我想他的回答(自从我上次更新我的App Engine以来),App Engine必须在此问题上进行升级。

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

非常感谢cletus 🙂

您可以使用contains方法

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