我使用数据存储本地api访问gae数据库(出于充分研究的具体原因)。我想优化代码并在我的请求中使用memcache而不是直接获取值,问题是我的查询是否已排序。
当我在查询中执行findProductsByFiltersQuery.setKeysOnly();
时,收到此错误:
提供的仅限密钥的多查询需要执行一些排序 记忆。因此,此查询只能按键排序 属性,因为这是内存中唯一可用的属性。
疲惫的事情是它从请求的某个复杂性开始发生,例如此请求失败:
SELECT __key__ FROM Product WHERE dynaValue = _Rs:2 AND productState = PUBLISHED AND dynaValue = _RC:2 AND dynaValue = RF:1 AND dynaValue = ct:1030003 AND dynaValue = _RS:4 AND dynaValue = _px:2 AND itemType = NEWS ORDER BY modificationDate DESC
虽然这个过去了:
SELECT __key__ FROM Product WHERE itemType = CI AND productState = PUBLISHED ORDER BY modificationDate DESC
有人可以解释一下为什么会发生这种情况,并且如果在获取密钥时无法进行排序,那该功能是什么? :由于结果是分页的,因此从第一个过滤请求中获取一组错误的密钥是没用的。那是怎么想的呢?
另请注意,当我执行非keysOnly
非常长的请求时,我会收到此消息
拆分提供的查询需要太多的子查询 合并在记忆中。
at com.google.appengine.repackaged.com.google.common.base.Preconditions.checkArgument(Preconditions.java:129)
at com.google.appengine.api.datastore.QuerySplitHelper.splitQuery(QuerySplitHelper.java:99)
at com.google.appengine.api.datastore.QuerySplitHelper.splitQuery(QuerySplitHelper.java:71)
有人可以解释一下,当索引值时,内存处理有可能吗?或者只是devmode服务器才会出现此错误?
答案 0 :(得分:1)
在数据存储区中使用OR
,IN
和!=
运算符时,必须进行内存中查询。作为described in this blog post,使用这些运算符的查询在客户端中分成多个数据存储区查询。例如:
SELECT * FROM Foo WHERE A = 1 OR A = 2
分为两个查询:
SELECT * FROM Foo WHERE A = 1
SELECT * FROM Foo WHERE A = 2
如果您在查询中添加ORDER BY B
,则两个子查询都会获得此订单:
SELECT * FROM Foo WHERE A = 1 ORDER BY B
SELECT * FROM Foo WHERE A = 2 ORDER BY B
虽然这些数据存储区查询中的每一个都返回按B排序的结果,但查询的并集却不是。在客户端,SDK合并了由B排序的两个结果。
为了做到这一点,数据存储区查询必须实际返回ordered属性,否则SDK不知道将这些属性合并在一起的正确方法。
如果您要编写包含大量过滤条件的查询,请务必仅使用AND
过滤条件。这将允许所有操作仅在数据存储区中执行,在这种情况下,不需要内存中的排序。