Tout d'abord, désolé pour mon mauvais anglais.Mongodb agrégat sur filtre comme sous-document
Si nous avons ci-dessous les documents à MongoDB,
Les données de test
{id:1, filter:{f1:'v1-1', f2:'v2-1', f3:['v3-1', 'v3-3']}}
{id:2, filter:{f1:'v1-1', f2:'v2-2', f3:['v3-2', 'v3-3']}}
{id:3, filter:{f1:'v1-1', f2:'v2-2', f3:['v3-1', 'v3-3']}}
Préparer la collection
db.test.drop()
db.test.insert({id:1, filter:{f1:'v1-1', f2:'v2-1', f3:['v3-1', 'v3-3']}})
db.test.insert({id:2, filter:{f1:'v1-1', f2:'v2-2', f3:['v3-2', 'v3-3']}})
db.test.insert({id:3, filter:{f1:'v1-1', f2:'v2-2', f3:['v3-1', 'v3-3']}})
Vous pouvez considérer le champ de filtre en fonction de filtre utilisé sur de nombreux sites de shopping, par exemple, ils vous diront combien LE D téléviseurs et combien de téléviseurs LCD sur le site. Je veux utiliser MongoDB pour calculer combien de documents avec chaque option de filtre (inclure chaque élément dans le champ tableau), le résultat attendu est comme ci-dessous.
Résultat attendu
[
{
_id : { key: 'f1', value: 'v1-1' }, count: 3
},
{
_id : { key: 'f2', value: 'v2-1' }, count: 1
},
{
_id : { key: 'f2', value: 'v2-2' }, count: 2
},
{
_id : { key: 'f3', value: 'v3-1' }, count: 2
},
{
_id : { key: 'f3', value: 'v3-2' }, count: 1
},
{
_id : { key: 'f3', value: 'v3-3' }, count: 3
}
]
Il est facile d'obtenir le résultat en utilisant la carte/réduire,
Map/Reduce solution
map = function() {
for (k in this.filter) {
if (this.filter[k] instanceof Array) {
for (j in this.filter[k]) {
emit({ key: k, value: this.filter[k][j]}, 1);
}
} else {
emit({ key: k, value: this.filter[k]}, 1);
}
}
}
reduce = function (k, values) {
result = 0;
values.forEach(function(v) { result += v; });
return result;
}
db.test.mapReduce(map, reduce, {out:{inline:1}})
Mais comme le problème de performance map/reduce, il ne peut pas être utilisé pour une requête en temps réel. et le jeu de résultats peut être modifié si j'ajoute des conditions de requête, donc je ne peux pas enregistrer la carte/réduire le résultat dans une autre collection pour une requête en temps réel.
Et je peux utiliser le cadre global pour calculer le nombre d'un filtre,
solution globale pour un seul filtre
db.test.aggregate(
{$project: {"filter.f2":1, "_id":0}},
{$group: {"_id": {"key": {$ifNull: [null, "f2"]}, "value":"$filter.f2"}, "count" : {$sum: 1}}}
)
[
{
"_id" : { "key" : "f2", "value" : "v2-2" }, "count" : 2
},
{
"_id" : { "key" : "f2", "value" : "v2-1" }, "count" : 1
}
]
Mais je ne sais pas comment faire pour tout filtre options Une idée?
Bonne réponse, merci! J'utilise mongodb 2.2, donc j'ai besoin d'utiliser '_id: {key:" $ key ", valeurs:" $ values "}' dans la section $ group. – jxie