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

Mongo Ordina per conteggio di corrispondenze nell'array

Per rispondere effettivamente prima, devi "calcolare" il numero di corrispondenze alla condizione data per "ordinare" i risultati per tornare con la preferenza al maggior numero di corrispondenze in cima.

Per questo è necessario il framework di aggregazione, che è quello che usi per il "calcolo" e la "manipolazione" dei dati in MongoDB:

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

Su un MongoDB precedente alla versione 3, puoi eseguire il modulo più lungo:

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 entrambi i casi la funzione qui è di far corrispondere prima i possibili documenti alle condizioni fornendo una "lista" di argomenti con $in . Una volta ottenuti i risultati, si desidera "contare" il numero di elementi corrispondenti nell'array nell'"elenco" di possibili valori forniti.

Nella forma moderna il $setIntersection l'operatore confronta i due "elenchi" restituendo un nuovo array che contiene solo i membri corrispondenti "unici". Dal momento che vogliamo sapere quante corrispondenze erano, restituiamo semplicemente il $size di quell'elenco.

Nelle versioni precedenti, dividi l'array di documenti con $unwind per eseguire operazioni su di esso poiché nelle versioni precedenti mancavano gli operatori più recenti che funzionassero con gli array senza alterazioni. Il processo esamina quindi ogni valore individualmente e se una delle espressioni in $or corrisponde ai valori possibili, quindi $cond ternario restituisce un valore di 1 al $sum accumulatore, altrimenti 0 . Il risultato netto è lo stesso "numero di partite" mostrato per la versione moderna.

L'ultima cosa è semplicemente $sort i risultati in base al "conteggio delle corrispondenze" che è stato restituito, quindi il maggior numero di corrispondenze è in "inizio". Questo è "ordine discendente" e quindi fornisci il -1 per indicarlo.

Addendum riguardante $in e gli array

Per cominciare, stai fraintendendo un paio di cose sulle query MongoDB. Il $in operatore è effettivamente inteso per un "elenco" di argomenti come questo:

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

Che è essenzialmente il modo abbreviato per dire "Abbina 'carota' o 'banana' nella proprietà 'Chiavi'" . E potrebbe anche essere scritto in forma lunga come questa:

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

Il che dovrebbe davvero portarti a se fosse una condizione di corrispondenza "singolare", quindi fornisci semplicemente il valore da abbinare alla proprietà:

{ "Keys": "carrot" }

Quindi questo dovrebbe coprire l'idea sbagliata che usi $in per abbinare una proprietà che è una matrice all'interno di un documento. Piuttosto il caso "inverso" è l'uso previsto in cui invece fornisci un "elenco di argomenti" per abbinare una determinata proprietà, che sia una proprietà un array o solo un singolo valore.

Il motore di query MongoDB non fa distinzione tra un singolo valore o una matrice di valori in un'operazione di uguaglianza o simile.