Du kan göra denna mapReduce operation.
Först kartläggaren:
var mapper = function () {
if ( this.flag == true ) {
totalCount++;
} else {
totalCount = 0;
}
if ( totalCount != 0 ) {
emit (
counter,
{ _id: this._id, totalCount: totalCount }
);
} else {
counter++;
}
};
Som håller en löpande räkning av det totala antalet gånger som true värdet ses i flaggan. Om antalet är mer än 1 så skickar vi värdet, som också innehåller dokumentet _id . En annan räknare som används för nyckeln inkrementeras när flaggan är false , för att ha en grupperings "nyckel" för matchningarna.
Sedan reduceraren:
var reducer = function ( key, values ) {
var result = { docs: [] };
values.forEach(function(value) {
result.docs.push(value._id);
result.totalCount = value.totalCount;
});
return result;
};
Tryck bara på _id värden på en resultatmatris tillsammans med totalCount.
Kör sedan:
db.people.mapReduce(
mapper,
reducer,
{
"out": { "inline": 1 },
"scope": {
"totalCount": 0,
"counter": 0
},
"sort": { "updated_at": 1 }
}
)
Så med mapper och reducer funktioner, definierar vi sedan de globala variablerna som används i "scope" och skickar in den "sort" som krävdes på updated_at datum. Vilket ger resultatet:
{
"results" : [
{
"_id" : 1,
"value" : {
"docs" : [
3,
4
],
"totalCount" : 2
}
},
{
"_id" : 2,
"value" : {
"docs" : [
7,
8,
5
],
"totalCount" : 3
}
}
],
"timeMillis" : 2,
"counts" : {
"input" : 7,
"emit" : 5,
"reduce" : 2,
"output" : 2
},
"ok" : 1,
}
Naturligtvis kan du bara hoppa över totalCount variabel och använd bara arraylängden, som skulle vara densamma. Men eftersom du ändå vill använda den räknaren är det bara att lägga till det. Men det är principen.
Så ja, detta var ett problem som lämpade sig för mapReduce, och nu har du ett exempel.