4

我正在尝试在 google 数据存储中查询类似的内容(使用 pm --> persistanceManager):

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

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

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

任何帮助表示赞赏!

4

8 回答 8

11

执行多个查询。与所有其他数据库一样,Datastore 无法有效地执行析取。与其他数据库不同,它向用户展示了这种困难,以明确您所做的事情效率不高。您唯一的解决方案是执行多个查询 - 每个查询一个或 - 并将它们组合起来。

于 2009-05-31T03:32:51.660 回答
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
}
于 2010-02-12T20:02:14.263 回答
2

根据Google App Engine - 查询和索引

查询过滤器

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

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

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

实体必须匹配所有过滤器才能成为结果。在 JDOQL 字符串语法中,多个过滤器由&&(逻辑“和”)分隔。不支持过滤器的其他逻辑组合(逻辑“或”、“非”)。

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

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

于 2009-05-31T00:59:47.977 回答
1

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

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

不幸的是,Google 决定他们不想推广这种低级 API 方法,而是更喜欢开发人员使用 JDO 或 JPA,因此除了 JavaDocs 和您在 Google“DatastoreService”时可能找到的任何代码示例之外,没有可用的文档.

TL

于 2009-07-07T18:47:03.630 回答
1

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

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

下次我会在行动之前更仔细地考虑。

TL

于 2009-07-09T19:27:55.623 回答
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));
   }
于 2009-06-08T20:30:11.663 回答
0

与 cletus 的回答相反,OR-ing无论如何在更新版本的 App Engine 中都有效。

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

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

我认为自从他的回答(并且自从我上次更新我的 App Engine 以来),App Engine 一定已经在这个问题上升级了。

将 App Engine 更新到 1.3.4,OR-ing 就可以工作了!虽然有限制。

无论如何都要感谢cletus:)

于 2010-06-11T15:51:01.913 回答
0

您可以使用 contains 方法

String filters = "( :values.contains(field) )";
Query query = pm.newQuery(myType.class, filters);
于 2015-07-22T10:10:36.333 回答