If you want to "weigh" the results according to certain criteria or have some kind of "calculated value" in the "sort", then you need .aggregate() . This allows you to use the "predicted" values in $sort , for which only the current field in the document can be used:
db.messages.aggregate([ { "$match": { "messages": userId } }, { "$project": { "recipients": 1, "unread": 1, "content": 1, "readYet": { "$setIsSubset": [ [userId], "$unread" ] } } }}, { "$sort": { "readYet": -1 } }, { "$limit": 20 } ])
Here the $setIsSubset operator allows $setIsSubset to compare an “unread” array with a transformed [userId] array to see if there are any Matches. The result will be either true where userId exists, or false where it is not.
This can then be passed to $sort , which orders the results with a preference for matches (decending sort true above) and, finally, $limit returns the results only up to the specified amount.
So, to use the term “sorting,” the value must be “projected” into the document so that it can be sorted. Aggregation structure is how you do it.
Also note that $elemMatch not only required to match a single value inside the array, and you only need to specify the value directly. Its purpose is that the conditions of "several" should be satisfied on one element of the array, which, of course, does not apply here.
source share