MongoDB 聚合:获取键值对的计数 [英] MongoDB aggregation: get counts of key, value pairs

查看:40
本文介绍了MongoDB 聚合:获取键值对的计数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个集合,其中的文档结构如下:

I have a collection that has documents structured like so:

{
  responses: {
    key1: bar,
    key2: quux
    ...
  },...
}

有没有办法获得 responses 对象中每个唯一键值对的计数?例如,我希望看到如下结果(具体结构无关紧要):

Is there a way to get the counts of each unique key, value pair in the responses object? For example, I'd like to see results like the following (the exact structure doesn't matter):

{
  key1: {
    foo: 7 // aka 7 objects are similar to { responses: [{key: foo}] }
    bar: 30
  },
  key2: {
    baz: 24,
    quux: 13
  }
}

推荐答案

有几种方法可以做到这一点.聚合框架还不能这样做,因为您无法将键名映射到值.但是 map reduce 让它变得相对简单:

There are a couple of ways to do this. Aggregation framework cannot do it yet because you cannot map key names to values. But map reduce makes it relatively straight forward:

map = function () { 
       for (k in this.responses) { 
          emit( { key: k, response: this.responses[k]}, 1 ); 
       } 
}

reduce = function (k, values) { 
       result = 0;  
       values.forEach( function(v) { result += v; } ); 
       return result; 
}

在此示例数据集上:

> db.responses.find({},{_id:0,responses:1}).pretty()
{ "responses" : { "key1" : "foo", "key2" : "bar" } }
{ "responses" : { "key1" : "foo", "key3" : "bar" } }
{ "responses" : { "key2" : "foo", "key3" : "bar" } }
{ "responses" : { "key3" : "baz" } }

运行 MR 让你:

> db.responses.mapReduce(map, reduce, {out:{inline:1}})
{
    "results" : [
        {
            "_id" : {
                "key" : "key1",
                "response" : "foo"
            },
            "value" : 2
        },
        {
            "_id" : {
                "key" : "key2",
                "response" : "bar"
            },
            "value" : 1
        },
        {
            "_id" : {
                "key" : "key2",
                "response" : "foo"
            },
            "value" : 1
        },
        {
            "_id" : {
                "key" : "key3",
                "response" : "bar"
            },
            "value" : 2
        },
        {
            "_id" : {
                "key" : "key3",
                "response" : "baz"
            },
            "value" : 1
        }
    ],
    "timeMillis" : 65,
    "counts" : {
        "input" : 4,
        "emit" : 7,
        "reduce" : 2,
        "output" : 5
    },
    "ok" : 1,
}

这是通过 mapreduce 执行此操作的第二种方法 - 这使输出更像您所说的您正在寻找的内容:

Here is the second way to do this via mapreduce - this gives output more like what you said you are looking for:

m2 = function () {
    for (k in this.responses) {
      keyname = this.responses[k];
      val = {};
      val[keyname] = 1;
      emit ( k, val );
    }
}
r2 = function (k, values) {
      result = { };
      values.forEach ( function(v) {
          for (k in v) {
             if (result[k] > 0) {
                result[k] += v[k];
             } else {
                result[k] = v[k];
             }
          }
      } );
      return result;
}

结果是:

> db.responses.mapReduce(m2, r2, {out:{inline:1}})
{
    "results" : [
        {
            "_id" : "key1",
            "value" : {
                "foo" : 2
            }
        },
        {
            "_id" : "key2",
            "value" : {
                "bar" : 1,
                "foo" : 1
            }
        },
        {
            "_id" : "key3",
            "value" : {
                "bar" : 2,
                "baz" : 1
            }
        }
    ],
    "timeMillis" : 3,
    "counts" : {
        "input" : 4,
        "emit" : 7,
        "reduce" : 3,
        "output" : 3
    },
    "ok" : 1,
}

这篇关于MongoDB 聚合:获取键值对的计数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆