有几个方法可以做到这一点。聚合框架无法完成,因为您无法将键名映射到值。但地图降低使得它相对简单:
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,
}
你事先知道所有的按键名称或没有? – 2013-05-11 03:29:02
不幸的是,我不知道关键的名字 - 会让事情变得更容易。它们与用户输入相关联。 – 2013-05-11 06:29:55