Puoi eseguire questa operazione mapReduce.
Innanzitutto il mappatore:
var mapper = function () {
if ( this.flag == true ) {
totalCount++;
} else {
totalCount = 0;
}
if ( totalCount != 0 ) {
emit (
counter,
{ _id: this._id, totalCount: totalCount }
);
} else {
counter++;
}
};
Che mantiene un conteggio progressivo delle volte totali che il true
il valore è visto in flag. Se quel conteggio è maggiore di 1, emettiamo il valore, contenente anche il documento _id
. Un altro contatore utilizzato per la chiave viene incrementato quando il flag è false
, per avere una "chiave" di raggruppamento per le partite.
Poi il riduttore:
var reducer = function ( key, values ) {
var result = { docs: [] };
values.forEach(function(value) {
result.docs.push(value._id);
result.totalCount = value.totalCount;
});
return result;
};
Semplicemente spinge il _id
valori su una matrice di risultati insieme a totalCount.
Quindi esegui:
db.people.mapReduce(
mapper,
reducer,
{
"out": { "inline": 1 },
"scope": {
"totalCount": 0,
"counter": 0
},
"sort": { "updated_at": 1 }
}
)
Quindi con il mapper
e reducer
funzioni, definiamo quindi le variabili globali utilizzate in "scope" e passiamo l'"ordinamento" richiesto su updated_at
date. Che dà il risultato:
{
"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,
}
Ovviamente puoi semplicemente saltare il totalCount
variabile e usa semplicemente la lunghezza dell'array, che sarebbe la stessa. Ma dal momento che vuoi comunque usare quel contatore, viene semplicemente aggiunto. Ma questo è il principio.
Quindi sì, questo era un problema adatto a mapReduce e ora hai un esempio.