sql >> Database teknologi >  >> NoSQL >> MongoDB

Mongo Sorter efter antal kampe i Array

For faktisk at svare på dette først, skal du "beregne" antallet af matches til den givne betingelse for at "sortere" resultaterne for at vende tilbage med præferencen til flest matcher øverst.

Til dette har du brug for aggregeringsrammerne, som er det du bruger til "beregning" og "manipulation" af data i MongoDB:

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

På en MongoDB ældre end version 3, så kan du gøre den længere form:

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

I begge tilfælde er funktionen her først at matche de mulige dokumenter til betingelserne ved at give en "liste" af argumenter med $in . Når resultaterne er opnået, vil du "tælle" antallet af matchende elementer i arrayet til "listen" over mulige værdier.

I den moderne form er $setIntersection operator sammenligner de to "lister" og returnerer et nyt array, der kun indeholder de "unikke" matchende medlemmer. Da vi gerne vil vide, hvor mange kampe det var, returnerer vi simpelthen $size af den liste.

I ældre versioner trækker du dokumentarrayet fra hinanden med $unwind for at udføre operationer på det, da ældre versioner manglede de nyere operatører, der arbejdede med arrays uden ændringer. Processen ser derefter på hver værdi individuelt og om enten udtryk i $or matcher de mulige værdier og derefter $cond ternary returnerer værdien 1 til $sum akkumulator, ellers 0 . Nettoresultatet er det samme "antal af kampe" som vist for den moderne version.

Den sidste ting er simpelthen at $sort resultaterne er baseret på "antal af kampe", der blev returneret, så de fleste kampe er på "top". Dette er "faldende rækkefølge", og derfor angiver du -1 for at indikere det.

Tillæg vedrørende $in og arrays

Du misforstår et par ting om MongoDB-forespørgsler til at begynde med. $in operatoren er faktisk beregnet til en "liste" af argumenter som denne:

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

Hvilket i bund og grund er den korte måde at sige "Match enten 'gulerod' eller 'banan' i ejendommen 'Nøgler'" . Og kunne endda skrives i lang form som denne:

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

Hvilket virkelig burde føre dig til, hvis det var en "enkelt" match-tilstand, så angiver du blot værdien for at matche ejendommen:

{ "Keys": "carrot" }

Så det burde dække over den misforståelse, at du bruger $in at matche en egenskab, der er en matrix i et dokument. Det "omvendte" tilfælde er snarere den tilsigtede brug, hvor du i stedet angiver en "liste over argumenter" for at matche en given egenskab, det være sig egenskaben en matrix eller blot en enkelt værdi.

MongoDB-forespørgselsmotoren skelner ikke mellem en enkelt værdi eller et array af værdier i en ligheds- eller lignende operation.




  1. Samme opgave udført flere gange

  2. Brug af Redis Object Cache til at fremskynde din WordPress-installation

  3. MongoDB starter ikke efter servernedbrud

  4. forbinder til lokal mongodb fra docker container