J'essaie d'utiliser une requête d'agrégation mongodb pour joindre deux collections ($ lookup) et ensuite compter toutes les valeurs uniques dans le tableau joint. * Note: Je ne sais pas nécessairement quels champs (clés) sont dans le tableau metaDataMap. Et je ne veux pas compter ou inclure des champs qui pourraient exister ou non sur la carte. C'est pourquoi la requête d'agrégation ressemble à cela.Problème de taille et de vitesse du pipeline d'agrégation Mongodb
donc mes deux collections ressemblent à ceci: Events-
{
"_id" : "1",
"name" : "event1",
"objectsIds" : [ "1", "2", "3" ],
}
Objets
{
"_id" : "1",
"name" : "object1",
"metaDataMap" : {
"SOURCE" : ["ABC", "DEF"],
"DESTINATION" : ["XYZ", "PDQ"],
"TYPE" : []
}
},
{
"_id" : "2",
"name" : "object2",
"metaDataMap" : {
"SOURCE" : ["RST", "LNE"],
"TYPE" : ["text"]
}
},
{
"_id" : "3",
"name" : "object3",
"metaDataMap" : {
"SOURCE" : ["NOP"],
"DESTINATION" : ["PHI", "NYC"],
"TYPE" : ["video"]
}
}
Mes résultats sont
{
_id:"SOURCE", count:5
_id:"DESTINATION", count: 4
_id:"TYPE", count: 2
}
Ce que j'est jusqu'à présent ceci:
db.events.aggregate([
{$match: {"_id" : id}}
,{$lookup: {"from" : "objects",
"localField" : "objectsIds",
"foreignField" : "_id",
"as" : "objectResults"}}
,{$unwind: "$objectResults"} //Line 1
,{$project: {x: "$objectResults.metaDataMap"}} //Line 2
,{$unwind: "$x"}
,{$project: {"_id":0}}
,{$project: {x: {$objectToArray: "$x"}}}
,{$unwind: "$x"}
,{$group: {_id: "$x.k", tmp: {$push: "$x.v"}}}
,{$addFields: {tmp: {$reduce:{
input: "$tmp",
initialValue:[],
in:{$concatArrays: [ "$$value", "$$this"]}
}}
}}
,{$unwind: "$tmp"}
,{$group: {_id: "$_id", uniqueVals: {$addToSet: "$tmp"}}}
,{$addFields: {count: {"$size":"$uniqueVals"}}}
,{$project: {_id: "$_id", count: "$count"}}
]);
Mon problème est ai-je été marqué ligne 1 & 2. Le travail ci-dessus, mais prend environ 50 secondes pour 25 000 valeurs dans les champs de tableau metaDataMap (objectsResults.metaDataMap). Ainsi, par exemple, avoir 25 000 valeurs dans le tableau de l'objet 1 metaDataMap SOURCE. C'est moyen de ralentir. Mon autre moyen plus rapide de le faire est de remplacer la ligne 1 & 2 avec:
,{$project: {x: "$objectResults.metaDataMap"}} //Line 1
,{$unwind: "$x"} //Line 2
C'est beaucoup plus rapide (moins de 3 secondes), mais ne peut être exécuté sur des ensembles de données qui ont ~ 10.000 articles ou moins. Quelque chose de plus élevé et je reçois une erreur disant "dépasse la taille maximale du document".
Aidez s'il vous plaît!
Pourrait ajouter un peu plus de description autour de "25.000 éléments dans divers tableaux"? –
Juste une pensée. Peut être que vous pouvez essayer de changer votre structure 'metaDataMap' en' 'metaDataMap": ["k": {"SOURCE", "v": ["ABC", "DEF"]} ... '' et insérer un ' $ map' stage après '$ lookup'. Quelque chose comme '{" $ project ": {" data ": {" $ map ": {" input ":" $ objectResults.metaDataMap "," as ":" resultom "," in ": {" $ map ": {"input": "$$ resultom", "comme": "resultim", "in": {"k": "$$ resultim.k", "v": {\t "$ size": \t "$ $ resultim.v "}}}}}}}}'. Je crois que de cette façon, vous pouvez obtenir la taille et le déroulement devrait être plus rapide. – Veeram
Mais je ne vais pas avoir un compte distinct avec la taille. Vais-je? J'ai besoin de déduire les valeurs v. – Deckard