web-dev-qa-db-fra.com

agrégat mongodb avec $ group et $ lookup

J'essaie d'effectuer un "groupe par" sur une table et de "la joindre" à une autre table. L'instruction SQL correspondante serait:

SELECT T1.total, T1.email, T1.type, table_2.name FROM
(SELECT SUM(amount) AS total, email, type 
FROM table_1
GROUP BY email, type) T1
INNER JOIN table_2
on T1.email = table_2.email 

Mais comme mongodb n’a toujours pas de fonctionnalité de jointure interne, j’ai essayé d’utiliser "$ lookup" et de faire la tâche. voici mon code:

db.table_1.aggregate([
{$group : {_id : {email: "$email", type:"$type"},total: { $sum: "$amount" }}},
{$lookup: {from: "table_2", localField: "email", foreignField: "email", as: "details"}} ]);

Mais dans les résultats que j'obtiens, les détails retournent et un objet vide:

{ "_id" : { "user" : "[email protected]", "type" : "Car" }, "total" : 2, "details" : [ ] }
{ "_id" : { "user" : "[email protected]", "type" : "Bike" }, "total" : 3, "details" : [ ] }
{ "_id" : { "user" : "[email protected]", "type" : "Car" }, "total" : 1, "details" : [ ] }

Mais si j'exécute la requête sans utiliser $ group, cela fonctionne bien. Je me demande donc si les fonctions $ group et $ lookup ne peuvent pas être utilisées ensemble. Si tel est le cas, existe-t-il un moyen de contourner le problème ou quel serait le moyen optimal de mener à bien la requête?

[version mongo db que j'utilise:> db.version () 3.2.7]

5
KTB

J'ai trouvé la réponse au problème. La raison pour laquelle j'ai obtenu un tableau vide est la manière dont j'ai utilisé le champ localField dans la recherche $.

Puisque j'essaie de joindre la table_2 avec le résultat $ group de la table_1, le champ local devrait être "_id.email".

Donc, la requête de travail serait:

db.table_1.aggregate([
    {$group : {_id : {email: "$email", type:"$type"},total: { $sum: "$amount" }}},
    {$lookup: {from: "table_2", localField: "_id.email", foreignField: "email", as: "details"}},
    {$match: {details: {$ne: []}}}
]);

Merci @Wake et @Clement pour l'aide

19
KTB

Si vous voulez que votre $ lookup fonctionne comme un INNER JOIN , c’est-à-dire que vous ne voulez pas de résultats sauf s’il existe au moins un document correspondant dans la table de recherche, vous pouvez ajouter un $ match à la fin de la comparaison des résultats de votre table de recherche avec un tableau vide [] :

db.table_1.aggregate([
    {$group : {_id : {email: "$email", type:"$type"},total: { $sum: "$amount" }}},
    {$lookup: {from: "table_2", localField: "email", foreignField: "email", as: "details"}},
    {$match: {details: {$ne: []}}}
]);
4
Wake

A partir de la version 3.2 de Mongo, $ lookup est utilisé pour prendre en charge la jointure gauche-externe. 

Je me demande si les fonctions $ group et $ lookup ne peuvent pas être utilisées Ensemble.

$ group et $ lookup peuvent être utilisés ensemble.

Comment l'utiliser pour INNER JOIN

Vous avez ajouté une condition supplémentaire pour filtrer les résultats. Utilisez $ match. Vous pouvez aussi essayer avec $ in.

Références

https://www.mongodb.com/blog/post/joins-and-other-aggregation-enhancements-coming-in-mongodb-3-2-part-1-of-3-introduction

http://www.clusterdb.com/mongodb/joins-and-other-aggregation-enhancements-in-mongodb-3-2

https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/

https://docs.mongodb.com/manual/reference/operator/aggregation/match/

1
Clement Amarnath