Elagin Vladislav
Elagin Vladislav

Reputation: 139

Mongo Aggregation multiple sorting stages (nodejs)

I am trying to build complex aggregation pipeline, which will fetch items from collection and sort them multiple times.

What I need is to: 1) get all users from collection 2) sort them by user-selected value (f.e. by amount of comments they left) 3) sort them by role (admin, moderator, basic-user)

Idea is to show admin user first even if some basic user have more comments, but if we have 2 admins - they would be sorted too.

Note that first $sort is to avoid unexpected sort+limit behavior, when items aren't fetched in constant order. Value of $skip is calculated while building pipeline depending on page number passed in API request.

For now I have something like this:

[
  { $match: <some condition> },
  { $sort: { _id: 1 } },
  { $sort: { countOfComment: -1 } },
  { $sort: { isAdmin: -1, isModerator: -1 } },
  { $skip: <page * 10> },
  { $limit: 10 }
]

If I got it right - it should: 1) get all users sorted by id, so there would be no duplications in different pages. this requires unique field to work 2) sort by amount of comments 3) sort by user role. It meant to save previous sorting results, so

- user with 4 comments
- moderator with 0 comments
- admin with 3 comments
- user with 2 comments
- admin with 1 comment

would become

- admin with 3 comments
- admin with 1 comment
- moderator with 0 comments
- user with 4 comments
- user with 2 comments

But it doesn't. Looks like each next $sort statement loses results of previous one. Any ideas how to reach desired behavior?

Upvotes: 1

Views: 846

Answers (2)

VIKAS KOHLI
VIKAS KOHLI

Reputation: 8470

You can merge sort in one object like:-

{ $sort: { countOfComment: 1, isAdmin: -1, isModerator: -1 } }

You can use $group for removing duplicate records and then use project and after that use the sort

Upvotes: 1

Elvis
Elvis

Reputation: 1143

You only need one sort stage, and that is,

    $sort: {
      isAdmin: -1,
      isModerator: -1,
      countOfComment: -1
    }

Basically, since you've sorted by countOfComment first, then the highest priority will be given to sorting by countOfComment. So, no matter what, the countOfComment field will definitely be sorted in descending order and only then will it see the next field to sort. Similarly, the last field will get the least priority while sorting.

The order in which you place the sort items is the order of priority.

Upvotes: 1

Related Questions