sql >> Databasteknik >  >> NoSQL >> MongoDB

Mongo Sortera efter antal matchningar i Array

För att faktiskt svara på detta först måste du "beräkna" antalet matchningar till det givna villkoret för att "sortera" resultaten för att återgå med preferensen till flest matchningar överst.

För detta behöver du aggregeringsramverket, vilket är vad du använder för "beräkning" och "manipulation" av 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 än version 3 kan du göra den längre formen:

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 båda fallen är funktionen här att först matcha de möjliga dokumenten med villkoren genom att tillhandahålla en "lista" med argument med $in . När resultaten har erhållits vill du "räkna" antalet matchande element i arrayen till "listan" över möjliga värden.

I den moderna formen $setIntersection operatorn jämför de två "listorna" och returnerar en ny array som bara innehåller de "unika" matchande medlemmarna. Eftersom vi vill veta hur många matchningar det var, returnerar vi helt enkelt $size på den listan.

I äldre versioner drar du isär dokumentmatrisen med $unwind för att utföra operationer på den eftersom äldre versioner saknade de nyare operatorerna som fungerade med arrayer utan förändring. Processen tittar sedan på varje värde individuellt och om antingen uttryck i $or matchar de möjliga värdena sedan $cond ternary returnerar värdet 1 till $sum ackumulator, annars 0 . Nettoresultatet är samma "antal matchningar" som visas för den moderna versionen.

Det sista är helt enkelt att $sort resultaten baserat på "antal matchningar" som returnerades så att flest matchningar är "överst". Detta är "fallande ordning" och därför anger du -1 för att indikera det.

Tillägg om $in och arrayer

Du missförstår ett par saker om MongoDB-frågor till att börja med. $in operatorn är faktiskt avsedd för en "lista" med argument som detta:

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

Vilket i grunden är förkortningen av att säga "Matcha antingen 'morot' eller 'banan' i fastigheten 'Keys'" . Och skulle till och med kunna skrivas i långform så här:

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

Vilket verkligen borde leda dig till om det var ett "singular" matchningsvillkor, då anger du helt enkelt värdet för att matcha egenskapen:

{ "Keys": "carrot" }

Så det borde täcka missuppfattningen att du använder $in för att matcha en egenskap som är en array i ett dokument. Snarare är det "omvända" fallet den avsedda användningen där du istället anger en "lista med argument" för att matcha en given egenskap, vare sig egenskapen är en matris eller bara ett enstaka värde.

MongoDB-frågemotorn gör ingen skillnad mellan ett enstaka värde eller en uppsättning värden i en likhet eller liknande operation.




  1. Meteor:Oväntad mongo exit-kod 100. Startar om. Kan inte starta mongo-servern

  2. Hur man formaterar tal i SQL

  3. Schemalägg Node.js-jobb var femte minut

  4. Fel:Kunde inte ansluta till Redis på redis:6379:Namn eller tjänst okänd