web-dev-qa-db-fra.com

$ match dans le résultat de la recherche $

J'ai le prochain code mongo:

db.users.aggregate([
    { 
        $match: { 
            $and: [
                { UserName: { $eq: 'administrator' } }, 
                { 'Company.CompanyName': { $eq: 'test' } }
            ]                   
        } 
    },
    { 
        $lookup: { 
            from: "companies", 
            localField: "CompanyID", 
            foreignField: "CompanyID", 
            as: "Company" 
        } 
    },
])

Le $lookup une partie du code fonctionne très bien. J'ai obtenu le résultat suivant:

enter image description hereenter image description here

Mais si j'ajoute $match au code, il n'apporte rien.

J'ai trouvé que le problème venait de la deuxième correspondance: { 'Company.CompanyName': { $eq: 'test' } }, mais je ne peux pas réaliser ce qui ne va pas. Des idées?

MISE À JOUR:

J'avais aussi essayé $unwind sur le $lookup résultat, mais pas de chance:

db.users.aggregate([
    { 
        $match: { 
            $and: [
                { UserName: { $eq: 'administrator' } }, 
                { 'Company.CompanyName': { $eq: 'edt5' } }
            ] 
        } 
    },
    {   unwind: '$Company' },
    { 
        $lookup: { 
            from: 'companies', 
            localField: 'CompanyID', 
            foreignField: 'CompanyID', 
            as: 'Company' 
        } 
    },
])
12
AlexBerd

Avec MongoDB 3.4, vous pouvez exécuter un pipeline d'agrégation qui utilise le $addFields pipeline et un $filter opérateur pour renvoyer uniquement le tableau Company avec des éléments qui correspondent à la condition donnée. Vous pouvez ensuite envelopper le $filter expression avec le $arrayElemAt opérateur pour renvoyer un seul document qui incorpore essentiellement $unwind fonctionnalité en aplatissant le tableau.

Suivez cet exemple pour comprendre le concept ci-dessus:

db.users.aggregate([
    { "$match": { "UserName": "administrator" } },
    { 
        "$lookup": { 
            "from": 'companies', 
            "localField": 'CompanyID', 
            "foreignField": 'CompanyID', 
            "as": 'Company' 
        } 
    },
    {
        "$addFields": {
            "Company": {
                "$arrayElemAt": [
                    {
                        "$filter": {
                            "input": "$Company",
                            "as": "comp",
                            "cond": {
                                "$eq": [ "$$comp.CompanyName", "edt5" ]
                            }
                        }
                    }, 0
                ]
            }
        }
    }
])
20
chridam

La réponse ci-dessous concerne mongoDB 3.6 ou version ultérieure.

Étant donné que:

  • Vous avez une collection users avec un champ CompanyID et une collection de companies avec un champ CompanyID
  • vous voulez rechercher Companies sur Users en faisant correspondre CompanyID, où en plus:

    • chaque utilisateur doit correspondre à la condition: User.UserName est égal à administrator
    • chaque Company sur User doit correspondre à la condition: CompanyName est égal à edt5

La requête suivante fonctionnera pour vous:

  db.users.aggregate([
    { $match: { UserName: 'administrator' } },
    {
      $lookup: {
        from: 'companies',
        as: 'Company',
        let: { CompanyID: '$CompanyID' },
        pipeline: [
          {
            $match: {
              $expr: {
                $and: [
                  { $eq: ['$CompanyID', '$$CompanyID'] },
                  { $eq: ['$CompanyName', 'edt5'] },
                ]
              }
            }
          }
        ]
      }
    },
  ])

Explication: C'est la façon d'effectuer des requêtes de jointure gauche avec des conditions plus complexes qu'une simple correspondance d'égalité de champ étranger/local.

Au lieu d'utiliser localField et foreignField, vous utilisez:

  • let option où vous pouvez mapper des champs locaux à des variables,
  • pipeline option où vous pouvez spécifier l'agrégation Array.

Dans pipeline, vous pouvez utiliser $match filtre, avec $expr, où vous pouvez réutiliser des variables définies précédemment dans let.

Plus d'informations sur $ lookup

joli tutoriel