Skip to content

Sorting by Relations

You can sort parent records by columns in related tables using dot notation in $sort.

belongsTo Sorting

For belongsTo (asArray: false) relations, sorting uses a LEFT JOIN:

ts
// Sort users by their manager's name
await app.service("users").find({
  query: { $sort: { "manager.name": 1 } },
});

Since there is at most one related record, no aggregation is needed.

hasMany Sorting

For hasMany (asArray: true) relations, sorting uses a subquery with an aggregate function to avoid duplicating parent rows:

  • Ascending — uses MIN() to pick the smallest value among related records
  • Descending — uses MAX() to pick the largest value among related records
ts
// Sort users by the MIN of their todos' text (ascending)
await app.service("users").find({
  query: { $sort: { "todos.text": 1 } },
});

// Sort users by the MAX of their todos' text (descending)
await app.service("users").find({
  query: { $sort: { "todos.text": -1 } },
});

INFO

Parents with no related records get NULL values, which sort according to your database's default NULL ordering.

You can narrow which related records are considered for sorting by providing a filter:

ts
// Sort users by the MIN text of only their todos assigned to user 1
await app.service("users").find({
  query: {
    $sort: {
      "todos.text": { direction: 1, filter: { assigneeId: 1 } },
    },
  },
});

Only todos where assigneeId = 1 are included in the MIN() aggregation.

Extended Sort Syntax

The full sort value can be either a direction or an object:

ts
// Simple form
$sort: { "todos.text": 1 }

// Extended form with filter
$sort: { "todos.text": { direction: 1, filter: { assigneeId: 1 } } }

Supported Sort Directions

ValueDirection
1 or '1'Ascending
-1 or '-1'Descending
'asc'Ascending
'desc'Descending
'asc nulls first'Ascending, nulls first
'asc nulls last'Ascending, nulls last
'desc nulls first'Descending, nulls first
'desc nulls last'Descending, nulls last

Combining Sorts

You can mix regular column sorts with relation sorts:

ts
await app.service("users").find({
  query: {
    $sort: {
      "todos.text": 1, // sort by related todo text
      name: -1, // then by user name descending
    },
  },
});