2017-07-20 3 views
0

J'ai 2 collections, dis A et B.

Exemple A:

[ 
    {"Account": "99", "Cat_1": "Losses", "Cat_2": "Marketing"}, 
    {"Account": "89", "Cat_1": "Losses", "Cat_2": "Consultancy"}, 
    {"Account": "79", "Cat_1": "Losses", "Cat_2": "Marketing"}, 
    {"Account": "69", "Cat_1": "Losses", "Cat_2": "Consultancy"}, 
    {"Account": "59", "Cat_1": "Profits", "Cat_2": "Marketing"}, 
    {"Account": "49", "Cat_1": "Profits", "Cat_2": "Consultancy"}, 
    {"Account": "29", "Cat_1": "Profits", "Cat_2": "Marketing"}, 
    {"Account": "00", "Cat_1": "Profits", "Cat_2": "Consultancy"} 
... 
] 

Exemple B:

[ 
    {"Name": "Example A", "Year": 2014, "Account": "99", "Amount": -5000}, 
    {"Name": "Example A", "Year": 2015, "Account": "99", "Amount": -5000}, 
    {"Name": "Example A", "Year": 2014, "Account": "89", "Amount": -2000}, 
    {"Name": "Example A", "Year": 2015, "Account": "79", "Amount": -3000}, 
    {"Name": "Example A", "Year": 2014, "Account": "69", "Amount": 0}, 
    {"Name": "Example A", "Year": 2015, "Account": "59", "Amount": 100}, 
    {"Name": "Example A", "Year": 2016, "Account": "49", "Amount": 5000}, 
    {"Name": "Example A", "Year": 2014, "Account": "29", "Amount": 4000}, 
    {"Name": "Example A", "Year": 2015, "Account": "00", "Amount": 900}, 
    {"Name": "Example B", "Year": 2013, "Account": "99", "Amount": -500}, 
    {"Name": "Example B", "Year": 2011, "Account": "89", "Amount": -10000}, 
    ... 
] 

Maintenant, je veux Par exemple, pour extraire tous les comptes "Cat_1" avec leur type pour aboutir à ceci:

[ 
    {"cat": "Losses", "Accounts": ["99", "89", "79", "69"]}, 
    {"cat": "Profits", "Accounts": ["59", "49", "29", "00"]} 
] 

Sinon, je voudrais aller chercher Cat_n pour une catégorie et obtenir un résultat similaire. Ensuite, je décompresse les comptes et effectue une recherche sur la collection B. C'est là que les choses tournent mal et que la taille maximale du document est dépassée. Je dois mentionner que je ne suis intéressé que 1 UTILISER à la fois, donc ma recherche ressemble à ceci au moment:

... 
{ 
    "$lookup": { 
    "from": "collection_B", 
    "localField": "Account", 
    "foreignField": "Account", 
    "as": "results" 
    } 
}, 
{ 
    "$addFields": { 
    "results": { 
     "$filter": { 
     "input": "$results", 
     "as": "comp", 
     "cond": { 
      "$eq": [ 
      "$$results.Name", "Example A" 
      ] 
     } 
     } 
    } 
    } 
}, 
... 

Après la recherche que j'utilise $addFields pour remplacer le champ de résultats d'origine, comme la plupart d'entre eux je Je ne veux pas parce que je ne suis intéressé que par des utilisateurs spécifiques.

Il y a environ 10M documents dans la deuxième collection, soit environ 300k par utilisateur. Donc, après cette recherche, il n'y a jamais plus de 300k dans le résultat. Lors de la demande des catégories cat_1, le résultat sera deux tableaux "Pertes" et "Profits" qui contiennent chacun environ 800 comptes.

Je réduis les tailles de document avec $project pour inclure seulement les champs que je veux réellement. De plus, j'utilise aussi $match le plus tôt possible pour éliminer les documents indésirables de l'agrégation. Cela n'aide pas, le document ne cesse de croître au-delà de la limite de 16 Mo BSON. Seulement lorsque vous utilisez $limit avec une valeur plutôt faible de ± 300, le résultat sera retourné et il manque des informations.

Ce que je suis finalement intéressé génère un documents qui contiennent quelque chose comme ceci pour une donnée et UTILISER Cat_n

{ 
    "Name": "Example A", 
    "Losses": [ 
    {"Year": 2014, "Amount": ...}, 
    {"Year": 2015, "Amount": ...}, 
    {"Year": 2016, "Amount": ...} 
    ], 
    "Profits": [ 
    {"Year": 2014, "Amount": ...}, 
    {"Year": 2015, "Amount": ...}, 
    {"Year": 2016, "Amount": ...} 
    ], 
} 

J'ai pensé à créer juste deux agrégations distinctes, l'une pour obtenir les catégories et 1 pour agréger les résultats de la collection B. Mais je devrais vérifier chaque document pour savoir à quelle catégorie il appartient, ce qui ne semble pas terriblement efficace. Alternativement, je pourrais créer une troisième collection où je fusionnerais les documents des deux collections et y ferais mes agrégats, mais si possible je préfère éviter cela car cela ajoute plus de complexité dans la maintenance ou la révision de ces données à un moment ultérieur.

+1

Avez-vous regardé cela "Modifié dans la version 2.6: La méthode db.collection.agrgregate() renvoie un curseur et peut renvoyer des ensembles de résultats de n'importe quelle taille.Les versions précédentes renvoyaient tous les résultats dans un document unique et le jeu de résultats était soumis à une limite de taille de 16 mégaoctets "https://docs.mongodb.com/manual/reference/method/db.collection.aggregate/ –

+0

@DanieleTassone, Bien que cela n'ait pas résolu mon problème maintenant, j'ai le sentiment que je pourrais l'utiliser quelque part sur la ligne – kbao

Répondre

-1

J'ai trouvé que le tableau de correspondance renvoyé par $ lookup dépassait la limite BSON de 16 Mo. Pour cette raison, il n'a pas été possible de récupérer les résultats de quelque façon que ce soit.

Géré pour le résoudre en inversant la logique, j'effectue maintenant une recherche à partir de la collection B dans A. Cela a vraiment plus de sens car je peux maintenant filtrer 94% des documents avant d'effectuer une recherche, au lieu de avoir à le faire après.

+1

Cela ressemble plus à une "solution de contournement" qu'à une solution. '$ match' directement après un' $ lookup' La raison en est que ces deux étapes de pipeline deviennent réellement partie de l'étape '$ lookup', le résultat est que vous récupérez seulement les données que vos conditions demandent et depuis leur" unwound " il n'est pas possible de franchir la limite de 16 Mo. Vous devez regarder la sortie "explain" pour voir l'effet réel sur le pipeline, je donne beaucoup plus de détails sur https://stackoverflow.com/a/44960412/2313887. vous pouvez faire la même chose dans l'autre sens. –