MongoDB 聚合:获取键值对的计数 [英] MongoDB aggregation: get counts of key, value pairs
问题描述
我有一个集合,其中的文档结构如下:
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屋!