Si vous voulez "pondérer" les résultats selon certains critères ou avoir n'importe quel type de "valeur calculée" dans un "tri", alors vous avez besoin du .aggregate()
méthode à la place. Cela permet aux valeurs "projetées" d'être utilisées dans le $sort
opération, pour laquelle seul un champ présent dans le document peut être utilisé :
db.messages.aggregate([
{ "$match": { "messages": userId } },
{ "$project": {
"recipients": 1,
"unread": 1,
"content": 1,
"readYet": {
"$setIsSubset": [ [userId], "$unread" ] }
}
}},
{ "$sort": { "readYet": -1 } },
{ "$limit": 20 }
])
Ici le $setIsSubset
L'opérateur permet la comparaison du tableau "non lu" avec un tableau converti de [userId]
pour voir s'il y a des correspondances. Le résultat sera soit true
où le userId existe ou false
où ce n'est pas le cas.
Cela peut ensuite être passé à $sort
, qui ordonne les résultats de préférence aux correspondances (le tri décroissant est true
en haut ), et enfin $limit
renvoie simplement les résultats jusqu'au montant spécifié.
Ainsi, afin d'utiliser un terme calulé pour "trier", la valeur doit être "projetée" dans le document afin qu'elle puisse être triée. Le cadre d'agrégation est la façon dont vous faites cela.
Notez également que $elemMatch
n'est pas nécessaire uniquement pour correspondre à une seule valeur dans un tableau, et vous n'avez qu'à spécifier la valeur directement. Son but est de remplir les conditions "multiples" sur un seul élément de tableau, ce qui bien sûr ne s'applique pas ici.