【问题标题】:Need a way to count entities in GAE datastore that meet a certain condition? (over 1000 entities)需要一种方法来计算 GAE 数据存储中满足特定条件的实体吗? (超过 1000 个实体)
【发布时间】:2010-02-04 17:02:37
【问题描述】:

我正在 GAE 上构建一个需要报告发生的事件的应用。一个事件有一个类型,我也需要按事件类型报告。

例如,假设有一个事件 A、B 和 C。它们周期性地随机发生。用户登录并创建一组实体,这些事件可以归因于这些实体。当用户回来检查状态时,我需要能够知道在特定时间范围内(比如一天或一个月)发生了多少 A、B 和/或 C 事件。

1000 个限制对我通常的操作方式造成了影响。我不需要检索所有实体并将它们呈现给用户,但我确实需要显示特定日期范围的总数。有什么建议吗?

我有点 python/GAE 菜鸟...

【问题讨论】:

标签: python google-app-engine google-cloud-datastore


【解决方案1】:

App Engine 不是关系型数据库,您无法像这样快速进行动态计数。最好的方法是在写入时更新计数,而不是在读取时生成它们。

在生成计数时,有两种通用方法可以很好地与 App Engine 一起使用,以最大限度地减少写入争用:

  1. 将计数存储在 Memcache 或本地内存中并定期刷新。这是最简单的解决方案,但它可能不稳定,并且可能会丢失数据。
  2. 使用Sharded Counter。这种方法更可靠但更复杂。您将无法轻松按计数排序,但您也可以定期刷新到另一个索引计数字段并按此排序。

【讨论】:

  • 这在这种情况下真的行不通 - 数据太细而无法有效分片。我还需要保留一段时间的历史记录。但是谢谢你的时间!
  • 阅读 Ikai 的链接 - 分片计数器不依赖于分片数据,而是依赖于分片计数器本身。
【解决方案2】:

数据存储 count() 查询的结果 和所有数据存储查询的偏移量 不再上限为 1000。

自 1.3.6 版起

【讨论】:

  • 我仍然达到 1000 个限制。
  • 干杯,但我需要计算超过 100,000 个实体。
  • @Gavin 然后使用 count(1000000) :) (处理如此大量实体的正确方法是在创建新实体时增加一个计数器)
  • 谢谢你 - 我会试一试的。可能比我的循环效率高一点!
【解决方案3】:

我的方法是使用一个或多个聚合模型来跟踪事件类型、日期和计数。不过,鉴于您的要求,我并不是 100% 应该如何建模。

然后,每当用户执行触发事件的操作时,我都会触发延迟任务以异步更新适当的聚合模型。

Nick Johnson 的 Background work with the deferred library 文章提供了更多信息,并提供了一个框架,您可能会发现它对您正在谈论的那种聚合很有用。

【讨论】:

  • 谢谢!我一定会检查出来的。主要问题是聚合计数不能很好地满足报告需求,尤其是在过滤数据时。正如前面提到的答案,关系数据库将是理想的,但我认为必须有一种方法来完成类似的事情。
  • 我也忘了补充一点平均值。我认为可以完成的一种方法是使用循环并“翻页”数据。每次返回时,对所有值求和并递增计数器。然后一旦它返回最后一个值,取总和除以计数器。但是,我不知道这是否适用于 .filter 属性或 GQL。有什么想法吗?
【解决方案4】:

solution 使用光标(如下所示)对您有用吗?我个人使用这种方法来计算与您类似的场景中的条目数,并且还没有看到任何问题(尽管我按计划运行,因为不断查询数据存储对 CPU 配额非常不利)。

def count(query): 
  i = 0 
  while True: 
    result = query.fetch(1000) 
    i = i + len(result) 
    if len(result) < 1000: 
      break 
    cursor = query.cursor() 
    query.with_cursor(cursor) 
  return i 

【讨论】:

    【解决方案5】:

    这篇文章很老了,但我想提供一个有用的参考。 App Engine 现在提供内置 API 来访问数据存储区统计信息:

    对于 Python,

    from google.appengine.ext.db import stats
    
    global_stat = stats.GlobalStat.all().get()
    print 'Total bytes stored: %d' % global_stat.bytes
    print 'Total entities stored: %d' % global_stat.count
    

    对于 Java,

    import com.google.appengine.api.datastore.DatastoreService;
    import com.google.appengine.api.datastore.DatastoreServiceFactory;
    import com.google.appengine.api.datastore.Entity;
    import com.google.appengine.api.datastore.Query;
    
    // ...
    DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
    Entity globalStat = datastore.prepare(new Query("__Stat_Total__")).asSingleEntity();
    Long totalBytes = (Long) globalStat.getProperty("bytes");
    Long totalEntities = (Long) globalStat.getProperty("count");
    

    也可以只过滤特定种类的实体编号。看看这个参考:

    https://developers.google.com/appengine/docs/python/datastore/stats https://developers.google.com/appengine/docs/java/datastore/stats

    【讨论】:

    • 另一种方法是在数据存储中保留一个计数器(您在每次添加/删除时更新),或者在必要时分片此计数器。 blog.svpino.com/2015/03/08/…
    • 有没有其他方法可以仅使用数据存储库获取整体实体状态?不使用app.engine 库!
    【解决方案6】:

    这听起来与我在 StackOverflow 上提出的问题非常相似。

    How to get the distinct value of one of my models in Google App Engine我需要知道如何为我的模型中的实体获取不同的值,并且该模型将有超过 1000 个实体。

    希望对您有所帮助。

    【讨论】:

    • 这是一个类似的问题,只是最终结果不是作为不同的实体输出,而是作为总和或平均值输出。谢谢!
    猜你喜欢
    • 2015-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-06
    • 1970-01-01
    • 1970-01-01
    • 2017-08-01
    相关资源
    最近更新 更多