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