web-dev-qa-db-fra.com

MongoDb: agrégation $ lookup avec filtrage sur les documents étrangers

Compte tenu de quelques collecitons:

1.- UTILISATEURS

{
  name: ...
  id: ...
  city: ...
  age: ...
  otherdata: ...
}

2.- ANIMAUX

{
  name: ...
  owner: ...
  type: ...
  age: ...
}

J'essaie d'utiliser l'agrégation avec $ lookup pour créer un ensemble d'objets qui représentent les utilisateurs avec leurs animaux de compagnie:

collectionusers.aggregate([
   {
     $lookup: {
       from: "pets",
       localField: "id",
       foreignField: "owner",
       as: "pets"
     }
   }
]);

Mais je voudrais ajouter un filtre pour que seuls les animaux de plus de 1 an soient ajoutés à chaque utilisateur (en utilisant l'âge du champ à l'intérieur des objets pour animaux de compagnie).

Le problème est que l'ajout de $ match dans l'agrégation ne fonctionne pas car il filtre les utilisateurs sans anciens animaux de compagnie, et je veux que les utilisateurs soient là même s'ils n'ont pas d'animaux.

En fait, j'essaie également d'obtenir uniquement le plus ancien des animaux de compagnie de chaque utilisateur et je n'ai pas non plus trouvé la formule.

Est-il possible d'exécuter cette action dans l'agrégation?

Bien sûr, actuellement je le fais après, sur les objets retournés.

Merci d'avance.

15
Gabriel

Vous pouvez utiliser $filter opérateur d'agrégation de tableaux sur pets tableau produit par votre $lookup étape.

Pour produire des animaux de plus de 1 an, utilisez

db.users.aggregate([ 
{ 
  $lookup: 
  { 
    from: "pets", 
    localField: "id", 
    foreignField: "owner", 
    as: "pets" 
  } 
}, 
{
  $project: 
  {
    name: 1,
    pets: 
    { 
      $filter: 
      { 
        input: "$pets", 
        as: "pet", 
        cond: { $gte: [ "$$pet.age", 1 ] } 
      } 
    } 
  } 
} 
]);

Pour afficher les animaux les plus âgés, remplacez simplement cond le champ $filter opérateur dans le pipeline d'agrégation précédent avec

cond: { $eq: [ "$$pet.age", { $max: "$pets.age" } ] }
15
tarashypka