Se vuoi "pesare" i risultati in base a determinati criteri o avere qualsiasi tipo di "valore calcolato" all'interno di un "ordinamento", allora hai bisogno di .aggregate()
metodo invece. Ciò consente di utilizzare valori "proiettati" nel $sort
operazione, per la quale è possibile utilizzare solo un campo presente nel documento:
db.messages.aggregate([
{ "$match": { "messages": userId } },
{ "$project": {
"recipients": 1,
"unread": 1,
"content": 1,
"readYet": {
"$setIsSubset": [ [userId], "$unread" ] }
}
}},
{ "$sort": { "readYet": -1 } },
{ "$limit": 20 }
])
Qui il $setIsSubset
consente di confrontare l'array "non letto" con un array convertito di [userId]
per vedere se ci sono corrispondenze. Il risultato sarà true
dove esiste l'ID utente o false
dove non lo fa.
Questo può quindi essere passato a $sort
, che ordina i risultati con preferenza alle corrispondenze (l'ordinamento decrescente è true
in alto ), e infine $limit
restituisce solo i risultati fino all'importo specificato.
Quindi, per utilizzare un termine calcolato per "ordina", il valore deve essere "proiettato" nel documento in modo che possa essere ordinato. Il framework di aggregazione è il modo in cui lo fai.
Nota anche che $elemMatch
non è richiesto solo per abbinare un singolo valore all'interno di una matrice e devi solo specificare direttamente il valore. Il suo scopo è dove devono essere soddisfatte condizioni "multiple" su un singolo elemento dell'array, il che ovviamente non si applica qui.