1

在我的 Google App Engine 应用程序中,我需要从数据存储查询中获取并返回可能大量的实体,以响应服务调用 GET 请求。此调用可能会返回数以千计的实体和 MB 的序列化数据。

响应数据包的第一部分传达序列化结果中有多少实体,然后是所有序列化实体。目前,我正在QueryResultIterator以最大页面大小限制遍历查询中的所有实体,之后我返回一个游标,可用于继续获取上一个调用停止的位置(如果达到最大值并且有仍然会导致查询)。当我遍历结果时,我将它们保存在一个列表中。一旦我用尽了查询结果或达到了最大页面大小,我就可以从这个列表的大小中获取实体的数量。但随后我必须再次遍历此列表以序列化每个实体并将结果写入响应输出流。

我不知道这是执行此操作的最有效方法。有没有一种方法可以在实际遍历所有实体或将它们直接提取到列表中之前获取查询结果中的实体数量?(list 方法无论如何都不起作用,因为我使用的是游标,这需要使用 QueryResultIterator)。

QueryResultIterator有方法getIndexList()。这是获取查询结果中实体数量的一种成本更低的方法吗?我假设这个列表将只包含查询结果中每个实体的一个索引对象。另外,我需要这个列表只包含插入器当前光标位置之后的实体索引。我的理解是否正确,或者这种方法不会像我想的那样做?

与加载整个实体列表相比,仅包含索引的列表需要的内存要少得多。虽然,我不知道这个列表是否会受到查询的预取或块大小的限制,或者我是否想使用查询的限制参数,因为我只想知道有多少实体在结果达到最大页面大小加一(知道还有更多结果并提供光标继续)。

目前我正在设置预取和块大小(到我的页面限制的大小),但我没有使用限制或偏移参数,因为我使用的是游标。据我了解,游标比偏移/限制更可取。设置限制参数会影响使用游标继续查询吗?

显然,关于 GAE 数据存储查询如何工作以及更改参数如何影响它们,我有很多问题。因此,任何见解都值得赞赏。App Engine API 的文档通常很少,就像一句话描述的方法一样,几乎可以从方法签名中推断出什么。否则,他们通常不会详细介绍。也许我目前这样做的方式毕竟很好。它按原样工作,但我正在尝试优化服务调用,以便为我的客户端应用程序获得最佳响应时间。

更新:顺便说一句,我在我的应用程序中使用Objectify v3 并执行此查询。我需要在几个地方使用低级数据存储 API,包括执行地理位置查询(使用geomodel)和投影查询(Objectify v3 不支持)。因此,如果有一个使用 Objectify 的好方法来做到这一点,那将是理想的。否则我可以使用低级 API,但这样总是比较麻烦。

4

2 回答 2

5

低级 api 和 Objectify 都有一个 count() 方法(有关详细信息,请查看 javadocs)。但是,计数可能是一项非常昂贵且耗时的操作 - 每个返回的数字都需要 1 个小操作。例如,返回 5000 的 count() 需要 5000 个小操作(加上 1 次读取用于查询),并且需要对所有 5000 个进行仅键扫描所需的时间(这是 GAE 实际所做的)。

如果您绝对必须有一个准确的计数,您可能需要自己通过增加/减少一个(可能是分片的)计数器来聚合这个值。当您处理过滤查询时,这会变得非常棘手。

这里没有一个正确的解决方案。Google 搜索会为您提供“大约 119,000,000 个结果”之类的总数,这些结果是故意不准确的,而且几乎可以肯定是预先计算的。对于较小的结果集,使用 count() 是可以接受的 - 但您可能希望应用 limit() 以便您永远不会破产。您总是可以说“超过 500 个结果...”

于 2013-06-13T15:02:11.060 回答
1

如果您想获取记录,则可以使用以下代码

  com.google.appengine.api.datastore.Query qry = new com.google.appengine.api.datastore.Query("EntityName");
  com.google.appengine.api.datastore.DatastoreService datastoreService = DatastoreServiceFactory.getDatastoreService();
  int totalCount = datastoreService.prepare(qry).countEntities(FetchOptions.Builder.withDefaults());

anf 如果你想要过滤器而不是你可以使用

qry.addFilter("firstName", FilterOperator.EQUAL, firstName);

我希望它会帮助你

于 2013-06-10T14:04:21.367 回答