這個問題似乎來了很多次,沒有解決方案。 我知道有兩種可能的解決方案: 解決方案1-使用mapReduce。 mapReduce是讓用戶可以做任何可以想象和編程的聚合的一般形式。
以下是使用mapReduce的mongo shell解決方案 我們考慮以下'st'集合。
db.st.find()
{ "_id" : ObjectId("51d6d23b945770d6de5883f1"), "foo" : "foo1", "bar" : "bar1" }
{ "_id" : ObjectId("51d6d249945770d6de5883f2"), "foo" : "foo2", "bar" : "bar2" }
{ "_id" : ObjectId("51d6d25d945770d6de5883f3"), "foo" : "foo2", "bar" : "bar22" }
{ "_id" : ObjectId("51d6d28b945770d6de5883f4"), "foo" : "foo2", "bar" : "bar3" }
{ "_id" : ObjectId("51d6daf6945770d6de5883f5"), "foo" : "foo3", "bar" : "bar3" }
{ "_id" : ObjectId("51d6db03945770d6de5883f6"), "foo" : "foo4", "bar" : "bar24" }
我們想按FOO,並且對於每個FOO,計數文檔的數量,以及文檔的與棒包含數子串「bar2'.that是:
foo1: nbdoc=1, n_match = 0
foo2: nbdoc=3, n_match = 2
foo3: nbdoc=1, n_match = 0
foo4: nbdoc=1, n_match = 1
爲了做到這一點,定義下列地圖功能
var mapFunction = function() {
var key = this.foo;
var nb_match_bar2 = 0;
if(this.bar.match(/bar2/g)){
nb_match_bar2 = 1;
}
var value = {
count: 1,
nb_match: nb_match_bar2
};
emit(key, value);
};
及以下減少功能
var reduceFunction = function(key, values) {
var reducedObject = {
count: 0,
nb_match:0
};
values.forEach(function(value) {
reducedObject.count += value.count;
reducedObject.nb_match += value.nb_match;
}
);
return reducedObject;
};
運行mapduce並將結果存儲在收集map_reduce_result
db.st.mapReduce(mapFunction, reduceFunction, {out:'map_reduce_result'})
{
"result" : "map_reduce_result",
"timeMillis" : 7,
"counts" : {
"input" : 6,
"emit" : 6,
"reduce" : 1,
"output" : 4
},
"ok" : 1,
}
最後,我們可以查詢集合map_reduce_result,瞧!使用兩個單獨的聚合和合並 解決
> db.map_reduce_result.find()
{ "_id" : "foo1", "value" : { "count" : 1, "nb_match" : 0 } }
{ "_id" : "foo2", "value" : { "count" : 3, "nb_match" : 2 } }
{ "_id" : "foo3", "value" : { "count" : 1, "nb_match" : 0 } }
{ "_id" : "foo4", "value" : { "count" : 1, "nb_match" : 1 } }
的2-我不會透露具體細節該解決方案爲任何蒙戈用戶可以很容易地做到這一點。 第1步:做聚合,忽略需要正則表達式求和的部分。 第二步:在第一步的同一個密鑰上進行第二次聚合分組。 管道的第一階段:匹配正則表達式; 階段2:與第一步相同的鍵上的組,計算每個組中的doc數{$ sum:1}; 步驟3:合併步驟1和2的結果:對於出現在兩個結果中的每個鍵添加新字段,如果鍵不存在,則在第二結果中將新鍵設置爲0。
Voila!另一種方案