我有一个MongoDB
集合,其中包含大约一百万条记录:
{
"_id" : ObjectId("53cf413e86763c3f2e6dca36"),
"test_data" : {
"status" : "pass",
"first_case" : [
{
"index" : "positionA_str",
"name" : "test_A",
},
{
"index" : "positionB_str",
"name" : "test_B",
}
],
"second_case" : [
{
"index" : "positionC_str",
"name" : "test_C",
},
{
"index" : "positionD_str",
"name" : "test_D",
}
]
}
}
我需要能够计算positionA_str
,positionB_str
,positionC_str
和positionD_str
的出现次数。
我做了一些研究,发现了一个简单的示例here,它向我展示了如何使用mapReduce
几乎完成此操作。
我想修改的映射函数是:
function wordMap(){
//find words in the document text
var word = this.text.match(/\w+/g);
if (word == null){
return;
}
for (var i = 0; i < word.length; i++){
emit(word[i], {count: 1});
}
}
因此,我需要修改第var word = this.text.match(/\w+/g);
行来计算属于index
的值。
但是,我无法找到如何做到这一点,因为它们发生在数组内部(first_case
下,second_case
下)。
例如,我想说的是:
var word = this.test_data.first_case[].index.match(/\w+/g);
但不允许使用[]
。而且,这并不包括index
second_case
的任何方式。
是否有人指出如何使用mapReduce
计算index
的每个值的出现次数,无论其在元素结构中的子位置如何?< /强>
非常感谢任何建议!
答案 0 :(得分:1)
不确定您认为您的示例与您要运行的查询有什么关系。你真正想要做的是将每个索引值“发出”为“键”,然后让“reducer”总结出现的事件:
db.collection.mapReduce(
// mapper
function () {
var mkeys = ['first_case','second_case'];
var test_data = this.test_data;
mkeys.forEach(function(k) {
test_data[k].forEach(function(data) {
emit( data.index, 1 );
});
});
},
// reducer
function(key,values) {
return Array.sum( values );
},
{ "out": { "inline": 1 } }
)
这真的是解决这个问题的最简单方法。只需循环每个数组并发出“index”字段值,然后“汇总”每个键上发出的1的所有值。
MapReduce将通过逐步调用该reducer来处理非常大的输入,直到每个键只剩下一个值。