MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Mongo Sortiert nach Anzahl der Übereinstimmungen im Array

Um dies tatsächlich zu beantworten, müssen Sie zuerst die Anzahl der Übereinstimmungen mit der gegebenen Bedingung „berechnen“, um die Ergebnisse so zu „sortieren“, dass sie mit der Präferenz zu den meisten Übereinstimmungen ganz oben zurückgegeben werden.

Dazu benötigen Sie das Aggregation Framework, das Sie zur „Berechnung“ und „Manipulation“ von Daten in MongoDB verwenden:

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

Auf einer MongoDB älter als Version 3 können Sie die längere Form verwenden:

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 } }
])

In beiden Fällen besteht die Funktion hier darin, zuerst die möglichen Dokumente den Bedingungen zuzuordnen, indem eine "Liste" von Argumenten mit $in bereitgestellt wird . Sobald Sie die Ergebnisse erhalten haben, möchten Sie die Anzahl der übereinstimmenden Elemente im Array auf die "Liste" der bereitgestellten möglichen Werte "zählen".

In der modernen Form der $setIntersection -Operator vergleicht die beiden "Listen" und gibt ein neues Array zurück, das nur die "eindeutigen" übereinstimmenden Mitglieder enthält. Da wir wissen wollen, wie viele Übereinstimmungen das waren, geben wir einfach die $size zurück dieser Liste.

In älteren Versionen ziehen Sie das Dokumenten-Array mit $unwind auseinander um Operationen darauf auszuführen, da älteren Versionen die neueren Operatoren fehlten, die unverändert mit Arrays arbeiteten. Der Prozess betrachtet dann jeden Wert einzeln und ob einer der Ausdrücke in $or steht den möglichen Werten entspricht, dann $cond ternary gibt einen Wert von 1 zurück zum $sum Akku, sonst 0 . Das Nettoergebnis ist dieselbe "Anzahl der Übereinstimmungen" wie für die moderne Version.

Das letzte ist einfach $sort Die Ergebnisse basieren auf der zurückgegebenen "Anzahl der Übereinstimmungen", sodass die meisten Übereinstimmungen "oben" stehen. Dies ist "absteigende Reihenfolge" und daher geben Sie den -1 an um darauf hinzuweisen.

Nachtrag bezüglich $in und Arrays

Für den Anfang missverstehen Sie ein paar Dinge über MongoDB-Abfragen. Der $in Operator ist eigentlich für eine "Liste" von Argumenten wie diese gedacht:

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

Das ist im Grunde die Kurzform für "Passt entweder zu 'Karotte' oder 'banana' in der Eigenschaft 'Keys'" . Und könnte sogar so in Langform geschrieben werden:

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

Was Sie wirklich dazu bringen sollte, wenn es sich um eine "singuläre" Übereinstimmungsbedingung handelt, geben Sie einfach den Wert an, der der Eigenschaft entspricht:

{ "Keys": "carrot" }

Das sollte also das Missverständnis abdecken, dass Sie $in verwenden um eine Eigenschaft abzugleichen, die ein Array innerhalb eines Dokuments ist. Vielmehr ist der "umgekehrte" Fall die beabsichtigte Verwendung, bei der Sie stattdessen eine "Liste von Argumenten" angeben, um eine bestimmte Eigenschaft abzugleichen, sei diese Eigenschaft ein Array oder nur ein einzelner Wert.

Die MongoDB-Abfrage-Engine unterscheidet nicht zwischen einem einzelnen Wert oder einem Array von Werten in einer Gleichheits- oder ähnlichen Operation.