我正在尝试查询google数据存储区(例如pm - > persistanceManager):
String filters = "( field == 'value' || field == 'anotherValue' )";
Query query = pm.newQuery(myType.class, filters);
当我执行时 - 我回来了: App Engine数据存储区不支持operator OR 。
人们在此类查询中遇到的最佳方法是什么?
任何帮助表示赞赏!
答案 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);