MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Mongo Trier par nombre de correspondances dans le tableau

Pour réellement répondre à cette première question, vous devez "calculer" le nombre de correspondances à la condition donnée afin de "trier" les résultats à renvoyer avec la préférence pour le plus de correspondances en premier.

Pour cela, vous avez besoin du framework d'agrégation, qui est ce que vous utilisez pour le "calcul" et la "manipulation" des données dans MongoDB :

db.multiArr.aggregate([
  { "$match": { "Keys": { "$in": [ "carrot", "banana" ] } } },
  { "$project": {
    "ID": 1,
    "Keys": 1,
    "order": {
      "$size": {
        "$setIntersection": [ ["carrot", "banana"], "$Keys" ]
      }
    }
  }},
  { "$sort": { "order": -1 } }
])

Sur une MongoDB antérieure à la version 3, vous pouvez alors faire le formulaire plus long :

db.multiArr.aggregate([
  { "$match": { "Keys": { "$in": [ "carrot", "banana" ] } } },
  { "$unwind": "$Keys" },
  { "$group": {
    "_id": "$_id",
    "ID": { "$first": "$ID" },
    "Keys": { "$push": "$Keys" },
    "order": {
      "$sum": {
        { "$cond": [
          { "$or": [
           { "$eq": [ "$Keys", "carrot" ] },
           { "$eq": [ "$Keys", "banana" ] }
         ]},
         1,
         0
        ]}
      }
    }
  }},
  { "$sort": { "order": -1 } }
])

Dans les deux cas, la fonction ici est d'abord de faire correspondre les documents possibles aux conditions en fournissant une "liste" d'arguments avec $in . Une fois les résultats obtenus, vous souhaitez "compter" le nombre d'éléments correspondants dans le tableau dans la "liste" des valeurs possibles fournies.

Dans la forme moderne, le $setIntersection L'opérateur compare les deux "listes" en renvoyant un nouveau tableau qui ne contient que les membres correspondants "uniques". Puisque nous voulons savoir combien de correspondances il y avait, nous renvoyons simplement le $size de cette liste.

Dans les anciennes versions, vous séparez le tableau de documents avec $unwind afin d'effectuer des opérations dessus car les anciennes versions manquaient des opérateurs plus récents qui fonctionnaient avec des tableaux sans modification. Le processus examine ensuite chaque valeur individuellement et si l'une ou l'autre des expressions dans $or correspond aux valeurs possibles puis le $cond ternaire renvoie une valeur de 1 à la $sum accumulateur, sinon 0 . Le résultat net est le même "nombre de correspondances" que celui indiqué pour la version moderne.

La dernière chose est simplement de $sort les résultats sont basés sur le « nombre de correspondances » qui a été renvoyé, de sorte que le plus de correspondances est sur « top ». C'est "l'ordre décroissant" et donc vous fournissez le -1 pour l'indiquer.

Addendum concernant $in et les tableaux

Vous comprenez mal certaines choses à propos des requêtes MongoDB pour les débutants. Le $in est en fait destiné à une "liste" d'arguments comme ceci :

{ "Keys": { "$in": [ "carrot", "banana" ] } }

Ce qui est essentiellement la manière abrégée de dire " Correspond à 'carotte' ou 'banana' dans la propriété 'Keys'" . Et pourrait même être écrit sous une forme longue comme ceci :

{ "$or": [{ "Keys": "carrot" }, { "Keys": "banana" }] }

Ce qui devrait vraiment vous conduire à s'il s'agissait d'une condition de correspondance "singulière", alors vous fournissez simplement la valeur à faire correspondre à la propriété :

{ "Keys": "carrot" }

Cela devrait donc couvrir l'idée fausse selon laquelle vous utilisez $in pour faire correspondre une propriété qui est un tableau dans un document. Le cas "inverse" est plutôt l'utilisation prévue où vous fournissez à la place une "liste d'arguments" pour correspondre à une propriété donnée, que cette propriété soit un tableau ou juste une valeur unique.

Le moteur de requête MongoDB ne fait aucune distinction entre une valeur unique ou un tableau de valeurs dans une égalité ou une opération similaire.