sql >> Database >  >> NoSQL >> MongoDB

Mongo Sorteren op aantal wedstrijden in array

Om dit eerst te beantwoorden, moet u het aantal overeenkomsten met de gegeven voorwaarde "berekenen" om de resultaten te "sorteren" om terug te keren met de voorkeur voor de meeste overeenkomsten bovenaan.

Hiervoor heb je het aggregatieraamwerk nodig, dat je gebruikt voor "berekening" en "manipulatie" van gegevens in MongoDB:

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

Op een MongoDB ouder dan versie 3, kunt u de langere vorm gebruiken:

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 beide gevallen is de functie hier om eerst de mogelijke documenten af ​​te stemmen op de voorwaarden door een "lijst" met argumenten te geven met $in . Zodra de resultaten zijn verkregen, wilt u het aantal overeenkomende elementen in de array "tellen" bij de "lijst" met mogelijke waarden.

In de moderne vorm de $setIntersection operator vergelijkt de twee "lijsten" en geeft een nieuwe array terug die alleen de "unieke" overeenkomende leden bevat. Omdat we willen weten hoeveel overeenkomsten dat waren, retourneren we gewoon de $size van die lijst.

In oudere versies trek je de documentarray uit elkaar met $unwind om er bewerkingen op uit te voeren, aangezien oudere versies de nieuwere operators misten die zonder wijziging met arrays werkten. Het proces kijkt dan naar elke waarde afzonderlijk en of een van beide expressies in $or komt overeen met de mogelijke waarden dan de $cond ternary retourneert een waarde van 1 naar de $sum accumulator, anders 0 . Het netto resultaat is hetzelfde "aantal wedstrijden" als getoond voor de moderne versie.

Het laatste is gewoon om $sort de resultaten zijn gebaseerd op het "aantal overeenkomsten" dat is geretourneerd, zodat de meeste overeenkomsten "bovenaan" staan. Dit is "aflopende volgorde" en daarom geeft u de -1 . op om dat aan te geven.

Aanvulling betreffende $in en arrays

U begrijpt een aantal dingen over MongoDB-query's voor beginners niet goed. De $in operator is eigenlijk bedoeld voor een "lijst" van argumenten zoals deze:

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

Dat is in wezen de verkorte manier om "Overeen te komen met 'wortel' of 'banaan' in de eigenschap 'Sleutels'" . En kan zelfs zo in lange vorm worden geschreven:

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

Wat er echt toe zou moeten leiden als het een "enkelvoudige" matchvoorwaarde zou zijn, dan geeft u gewoon de waarde op die overeenkomt met de eigenschap:

{ "Keys": "carrot" }

Dus dat zou de misvatting moeten dekken dat je $in . gebruikt om te matchen met een eigenschap die een array is in een document. Het "omgekeerde" geval is eerder het beoogde gebruik, waarbij u in plaats daarvan een "lijst met argumenten" opgeeft die overeenkomen met een bepaalde eigenschap, of die eigenschap nu een array is of slechts een enkele waarde.

De MongoDB-query-engine maakt geen onderscheid tussen een enkele waarde of een reeks waarden in een gelijkheids- of vergelijkbare bewerking.




  1. Communicatie tussen twee Docker-containers op macOS 10.12

  2. Splits string in een array van substrings of karakters in MongoDB

  3. Bereikquery's in Redis - Spring Data Redis

  4. hoe kan ik oneindig doorgeven aan redis van python?