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.