Mongo sorting by design condition

I have a Mongo message compilation that looks like this:

{ 'recipients': [], 'unRead': [], 'content': 'Text' } 

Recipients are an array of user identifiers, and unRead is an array of all users who have not yet opened a message. This works as intended, but I need to request a list of all messages so that it returns the first 20 results, first setting the priorities of unread, for example:

 db.messages.find({recipients: {$elemMatch: userID} }) .sort({unRead: {$elemMatch: userID}}) .limit(20) 

But that does not work. What is the best way to prioritize results based on whether they meet certain criteria?

+5
source share
1 answer

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.

+5
source

Source: https://habr.com/ru/post/1233004/


All Articles