Você pode fazer esta operação mapReduce.
Primeiro o mapeador:
var mapper = function () {
if ( this.flag == true ) {
totalCount++;
} else {
totalCount = 0;
}
if ( totalCount != 0 ) {
emit (
counter,
{ _id: this._id, totalCount: totalCount }
);
} else {
counter++;
}
};
Que mantém uma contagem contínua do total de vezes que o
true
valor é visto em flag. Se essa contagem for maior que 1, emitimos o valor, também contendo o documento _id
. Outro contador que é usado para a chave é incrementado quando o sinalizador é false
, para ter uma "chave" de agrupamento para as partidas. Então o redutor:
var reducer = function ( key, values ) {
var result = { docs: [] };
values.forEach(function(value) {
result.docs.push(value._id);
result.totalCount = value.totalCount;
});
return result;
};
Simplesmente empurra o
_id
valores em uma matriz de resultados junto com totalCount. Então corra:
db.people.mapReduce(
mapper,
reducer,
{
"out": { "inline": 1 },
"scope": {
"totalCount": 0,
"counter": 0
},
"sort": { "updated_at": 1 }
}
)
Assim, com o
mapper
e reducer
funções, então definimos as variáveis globais usadas em "scope" e passamos o "sort" que foi necessário em updated_at
datas. O que dá o resultado:{
"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,
}
Claro que você pode simplesmente pular o
totalCount
variável e use apenas o comprimento do array, que seria o mesmo. Mas como você quer usar esse contador de qualquer maneira, ele é apenas adicionado. Mas esse é o princípio. Então sim, este era um problema adequado para mapReduce, e agora você tem um exemplo.