有几种方法可以做到这一点。聚合框架还不能做到这一点,因为您无法将键名映射到值。但是 map reduce 让它变得相对简单:
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 执行此操作的第二种方法-这使输出更像您所说的要查找的内容:
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,
}