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