3
votes

Trouver l'élément max dans un tableau

REF: MongoDB Document du tableau avec une valeur de champ max a >

Réponses dans Recherche de la valeur la plus élevée à partir des sous-tableaux dans les documents et MongoDB trouvent par valeur maximale dans un tableau de documents suggère d'utiliser sort + limit (1), mais c'est vraiment lent. Il existe sûrement un moyen d'utiliser l'opérateur $ max.

Supposons que l'on obtienne un document comme celui-ci dans une correspondance globale:

age: {$eq: {$max: "$age"}}

Et vous voulez trouver le document (entier, pas seulement la valeur unique) où l'âge est le plus élevé. Comment faire cela avec l'opérateur $ max?

J'ai essayé

{
  _id: null,
  name: "Peter",
  age: 17
}
{
  _id: null,
  name: "Carl",
  age: 21
}
{
  _id: null,
  name: "Ben",
  age: 15
}

donc j'obtiens

unwind {"$array"}
project {"_id": 0, "name": "$array.name", "age": "$array.age"}

Ensuite, j'ai essayé de faire correspondre l'âge:

{
  _id: "notImportant",
  array: [
    {
      name: "Peter",
      age: 17
    },
    {
      name: "Carl",
      age: 21
    },
    {
      name: "Ben",
      age: 15
    }
  ]
}

, mais cela ne me donne aucun résultat.

En d'autres termes, ce que je dois obtenir, c'est le nom et tous les autres champs appartenant à la personne la plus âgée du tableau. Et il y a plusieurs milliers de personnes, avec beaucoup d'attributs, et en plus de tout cela, il fonctionne sur un Raspberry Pi. Et je dois faire cette opération sur quelques dizaines de ces tableaux. Donc, avec le tri, cela prend environ 40 secondes au total. Je voudrais donc vraiment ne pas utiliser le tri.


3 commentaires

L'une des réponses dans les doublons marqués stackoverflow.com/a/14898039/122005 utilise $ max


cette réponse obtient la valeur maximale de K et la valeur maximale de V, mais elles ne sont pas liées. Dans mon exemple, s'il y avait, disons un attribut de hauteur pour que les gens donnent leur taille, cela renverrait la plus grande taille et le plus grand âge, mais ils pourraient ne pas être liés à la même personne (entrée dans le tableau.) Ou ai-je vous vous trompez?


@chridam la question a une réponse encore meilleure. Sans $ unwind :-)


3 Réponses :


3
votes

pouvez-vous essayer cette agrégation avec $reduce

{ "_id" : "notImportant", "array" : { "name" : "Carl", "age" : 21 } }

output

db.t63.aggregate([
    {$addFields : {array : {$reduce : {
        input : "$array", 
        initialValue : {age : 0}, 
        in : {$cond: [{$gte : ["$$this.age", "$$value.age"]},"$$this", "$$value"]}}
    }}}
])


1 commentaires

C'est à ce jour que les réponses sont les plus flexibles. Comme je dois également filtrer l'âge (entre min et max), cela fonctionne pour moi.



3
votes

Si vous voulez tous les documents qui ont la valeur la plus élevée, vous devez utiliser un filtre. Donc, fondamentalement, au lieu d'utiliser ces déroulements, projets, etc., utilisez simplement l'étape de projet ci-dessous

                $project: {
                    age: {
                        $filter: {
                            input: "$array",
                            as: "item",
                            cond: { $eq: ["$$item.age", { $max: "$array.age" }] }
                        }
                    }
                }


0 commentaires

1
votes

Vous pouvez utiliser ci-dessous aggregation

db.collection.aggregate([
  { "$project": {
    "max": {
      "$arrayElemAt": [
        "$array",
        {
          "$indexOfArray": [
            "$array.age",
            { "$max": "$array.age" }
          ]
        }
      ]
    }
  }}
])


0 commentaires