MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Mehrere Join-Bedingungen mit dem $lookup-Operator

Mit $lookup können wir mehrere Join-Bedingungen erstellen Aggregation-Pipeline-Operator in Version 3.6 und höher.

Wir müssen die Werte der Felder mithilfe von let einer Variablen zuweisen optionales Feld; Sie greifen dann auf diese Variablen in der pipeline zu Feldphasen, in denen Sie die Pipeline angeben, die auf den Sammlungen ausgeführt werden soll.

Beachten Sie das im $match Stufe verwenden wir den $expr Auswertungsabfrageoperator zum Vergleichen der Werte der Felder.

Die letzte Stufe in der Pipeline ist $replaceRoot Aggregation-Pipeline-Phase, in der wir einfach $lookup zusammenführen Ergebnis mit einem Teil des $$ROOT Dokument mit $mergeObjects Betreiber.

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"
                   }
                ]
             }
          }
       }
    ]
)

Diese Pipeline ergibt etwas, das so aussieht:

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

Wenn Sie nicht auf Version 3.6 oder höher sind, können Sie zuerst mit einem Ihrer Felder beitreten, sagen wir "user1", dann wickeln Sie das Array des übereinstimmenden Dokuments mit dem $unwind ab Aggregations-Pipeline-Betreiber. Die nächste Stufe in der Pipeline ist $redact Phase, in der Sie mithilfe von $$KEEP die Dokumente herausfiltern, bei denen der Wert von „user2“ aus der „joined“-Sammlung und dem Eingabedokument nicht gleich sind und $$PRUNE Systemvariablen. Anschließend können Sie Ihr Dokument in $project umformen Stufe.

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"
    }}
])

was produziert:

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

Wenn die Dokumente in Ihren Sammlungen dieselbe Struktur haben und Sie diesen Vorgang häufig durchführen, sollten Sie in Betracht ziehen, die beiden Sammlungen zu einer zusammenzuführen oder die Dokumente in diesen Sammlungen in eine neue Sammlung einzufügen.

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

Dann $group Ihre Dokumente nach "user1" und "user2"

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

was ergibt:

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