MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Conditions de jointure multiples à l'aide de l'opérateur $lookup

Nous pouvons faire plusieurs conditions de jointure avec le $lookup opérateur de pipeline d'agrégation dans la version 3.6 et les versions ultérieures.

Nous devons attribuer les valeurs des champs à la variable en utilisant le let champ facultatif ; vous accédez ensuite à ces variables dans le pipeline étapes de champ où vous spécifiez le pipeline à exécuter sur les collections.

Notez que dans le $match étape, nous utilisons le $expr opérateur de requête d'évaluation pour comparer la valeur des champs.

La dernière étape du pipeline est le $replaceRoot étape de pipeline d'agrégation où nous fusionnons simplement le $lookup résultat avec une partie de $$ROOT document utilisant $mergeObjects opérateur.

db.collection2.aggregate([
       {
          $lookup: {
             from: "collection1",
             let: {
                firstUser: "$user1",
                secondUser: "$user2"
             },
             pipeline: [
                {
                   $match: {
                      $expr: {
                         $and: [
                            {
                               $eq: [
                                  "$user1",
                                  "$$firstUser"
                               ]
                            },
                            {
                               $eq: [
                                  "$user2",
                                  "$$secondUser"
                               ]
                            }
                         ]
                      }
                   }
                }
             ],
             as: "result"
          }
       },
       {
          $replaceRoot: {
             newRoot: {
                $mergeObjects:[
                   {
                      $arrayElemAt: [
                         "$result",
                         0
                      ]
                   },
                   {
                      percent1: "$$ROOT.percent1"
                   }
                ]
             }
          }
       }
    ]
)

Ce pipeline donne quelque chose qui ressemble à ceci :

{
    "_id" : ObjectId("59e1ad7d36f42d8960c06022"),
    "user1" : 1,
    "user2" : 2,
    "percent" : 0.3,
    "percent1" : 0.56
}

Si vous n'êtes pas sur la version 3.6+, vous pouvez d'abord rejoindre en utilisant l'un de vos champs disons "user1" puis à partir de là vous déroulez le tableau du document correspondant en utilisant le $unwind opérateur de pipeline d'agrégation. La prochaine étape du pipeline est le $redact étape où vous filtrez les documents où la valeur de "user2" de la collection "jointe" et le document d'entrée ne sont pas égaux en utilisant le $$KEEP et $$PRUNE variable système. Vous pouvez ensuite remodeler votre document dans $project scène.

db.collection1.aggregate([
    { "$lookup": { 
        "from": "collection2", 
        "localField": "user1", 
        "foreignField": "user1", 
        "as": "collection2_doc"
    }}, 
    { "$unwind": "$collection2_doc" },
    { "$redact": { 
        "$cond": [
            { "$eq": [ "$user2", "$collection2_doc.user2" ] }, 
            "$$KEEP", 
            "$$PRUNE"
        ]
    }}, 
    { "$project": { 
        "user1": 1, 
        "user2": 1, 
        "percent1": "$percent", 
        "percent2": "$collection2_doc.percent"
    }}
])

qui produit :

{
    "_id" : ObjectId("572daa87cc52a841bb292beb"),
    "user1" : 1,
    "user2" : 2,
    "percent1" : 0.56,
    "percent2" : 0.3
}

Si les documents de vos collections ont la même structure et que vous effectuez souvent cette opération, vous devriez envisager de fusionner les deux collections en une seule ou d'insérer les documents de ces collections dans une nouvelle collection.

db.collection3.insertMany(
    db.collection1.find({}, {"_id": 0})
    .toArray()
    .concat(db.collection2.find({}, {"_id": 0}).toArray())
)

Puis $group vos documents par "user1" et "user2"

db.collection3.aggregate([
    { "$group": {
        "_id": { "user1": "$user1", "user2": "$user2" }, 
        "percent": { "$push": "$percent" }
    }}
])

ce qui donne :

{ "_id" : { "user1" : 1, "user2" : 2 }, "percent" : [ 0.56, 0.3 ] }