【问题标题】:SELECT COUNT(DISTINCT *) in CouchDB在 CouchDB 中选择 COUNT(DISTINCT *)
【发布时间】:2016-02-07 21:54:27
【问题描述】:

我有符合这种格式的文件:

{
  "_id": "some_doc_id", 
  "user": "some_user_id", 
  "date": "2015-09-15",
  …
}

同一用户可以拥有多个文档。我想计算两个日期之间有多少不同的用户。例如。在“2015-09-15”和“2015-09-25”之间,有 745 个不同的用户。

在 SQL 中,我会写这个查询:

SELECT COUNT(DISTINCT user)
FROM documents
WHERE date BETWEEN '2015-09-15' and '2015-09-25' 

谢谢。

【问题讨论】:

    标签: mapreduce couchdb nosql


    【解决方案1】:

    我会使用如下地图函数:

    function (doc) {
      emit(doc.date, doc.user);
    }
    

    它将发出按日期排序的文档,其中用户是值。 reduce 函数如下所示:

    function(keys, values, rereduce) {
      if (rereduce) {
        return values.reduce(function (acc, index) {
          return Object.keys(index).reduce(function (acc, user) {
            acc[user] = (acc[user] || 0) + index[user];
            return acc;
          }, acc);
        }, {});
      } else {
        return values.reduce(function (acc, user) {
          if (!(user in acc)) acc[user] = 0;
          acc[user]++;
          return acc;
        }, {});
      }
    }
    

    这是一个自定义的 reduce 函数,所以请耐心等待我的简要说明。正常情况(第二个分支,而不是rereduce)基本上计算了它找到的值。结果是像{ some_user_id: 1 } 这样的对象。

    rereduce 分支基本上采用几个缩减的对象并将它们(及其计数)合并为 1 个缩减的结果。 (你可以阅读更多关于reduce和rereduce的信息here

    从那里,您可以使用以下查询参数查询您的视图:

    start_key="2015-09-15"
    end_key="2015-09-25"
    

    您最终会得到与前面所示相同的结果。 (即:{ some_user_id: 1 })在您的客户端上,您可以计算结果对象中的键,以了解在任何给定日期范围内有多少唯一用户。

    【讨论】:

    • 虽然看起来是确定性的,但恐怕随着reduce值的增长(第12行)会达到“reduce limit”。我应该禁用 reduce_limit 选项以确保安全吗? (至少对于第一个索引)。此外,在我看来,索引会花费大量时间,也许我应该在 Erlang 中编写这个 reduce 函数。谢谢。
    • 这是可能的。如果您担心减少限制,我会等到它成为实际问题后再禁用。如果它确实成为问题,您可以改为在不存在这些限制的_list 函数中进行缩减。
    猜你喜欢
    • 1970-01-01
    • 2010-12-04
    • 2013-06-19
    • 2019-11-18
    • 2015-05-01
    • 2011-10-06
    • 1970-01-01
    • 2021-03-06
    • 1970-01-01
    相关资源
    最近更新 更多