Comment ajouter une condition dans $ lookup dans MongoDb .aggregate ()?

Sep 03 2020

collection de personnes:

{
  "_id": ObjectId("5f3258cfbaaccedaa5dd2c96"),
  "gender": "male",
  "name": {
    "title": "mr",
    "first": "victor",
    "last": "pedersen",//... more properties
} 

collection de détails personnels:

{
      "_id": ObjectId("5f3a91e68b1c26e68f9ed3ad"),
      "country": "India",
      "personid": ObjectId("5f3258cfbaaccedaa5dd2c96")
}

Obtenez des documents de personnes ainsi que des détails personnels associés où le pays associé dans les détails personnels est "Inde

Donc, si sur 10 personnes seulement 3 sont originaires d'Inde. Je devrais obtenir les documents de 3 personnes dans l'ensemble de résultats avec leurs détails personnels associés

Requete:

 [
    {
      "$match": { "$or": [
         
        {
          "$expr": { "$eq": [
              "$gender", "male" ] } } ] } }, { "$facet": {
      "totalCount": [
        {
          "$count": "value" } ], "data": [ { "$project": {
            "_id": "$_id", "fname": "$name.first",
            "lname": "$name.last", "dobage": "$dob.age",
            "registeredAge": "$registered.age" } }, { "$sort": {
            "name.first": 1
          }
        } ,
        {
          "$lookup": {
            "from": "persondetails",
            "localField": "_id",
            "foreignField": "personid", // how to add where clause in this lookup?
            "as": "persondetail" 
          }
        }
      ]
    }
  }
]

ÉDITER:

https://mongoplayground.net/p/3vBs6Frt-aK

Résultat attendu:

[
  {
    "data": [
      {
        "_id": ObjectId("5f3258cfbaaccedaa5dd2c96"),
        "fname": "victor",
        "lname": "pedersen",
        "persondetail": [
          {
            "_id": ObjectId("5f3a91e68b1c26e68f9ed3ad"),
            "country": "India",
            "personid": ObjectId("5f3258cfbaaccedaa5dd2c96")
          }
        ]
      }],
    "totalCount": [
      {
        "value": 1
      }
    ]
  }
]

Réponses

2 mickl Sep 02 2020 at 23:04

Il existe une deuxième syntaxe $ lookup qui vous permet de spécifier une condition de filtrage personnalisée:

{
    "$lookup": {
        "from": "persondetails",
        "let": { person_id: "$_id" }, "pipeline": [ { $match: {
                    $expr: { $and: [
                            { $eq: [ "$$person_id", "$personid" ] }, { $eq: [ "$country", "India" ] },
                        ]
                    }
                }
            }
        ],
        "as": "persondetail" 
    }
}

EDIT: Vous devez également ajouter $ match pour filtrer les personnes vides persondetailet si vous voulez que cela soit inclus dans votre décompte, vous devez exécuter $ facet comme dernière opération:

[
    {
        "$match": {
            "$or": [ {"$expr": { "$eq": [ "$gender", "male" ] } } ]
        }
    },
    {
        "$project": { "_id": "$_id",
                "fname": "$name.first", "lname": "$name.last",
                "dobage": "$dob.age", "registeredAge": "$registered.age"                
        }
    },    
    {
        "$lookup": { "from": "persondetails", "let": { person_id: "$_id" },
            "pipeline": [
                {
                    $match: { $expr: {
                            $and: [ { $eq: [ "$$person_id", "$personid" ] },
                                { $eq: [ "$country", "India" ] },
                            ]
                        }
                    }
                }
            ],
            "as": "persondetail" 
        }
    },
    {
        $match: { persondetail: { $ne: [] }
        }
    },
    {
        $facet: { totalCount: [ { $count: "value" } ],
            data: [ { $sort: { "name.first": 1 } },  ]
        }
    }
]

Aire de jeux Mongo