Skip to main content

Sort Query Results

Order by field value

  • Use OrderBy or OrderByDescending to order the results by the specified document-field.
List<Product> products = session
// Make a dynamic query on the Products collection
.Query<Product>()
// Apply filtering (optional)
.Where(x => x.UnitsInStock > 10)
// Call 'OrderBy', pass the document-field by which to order the results
.OrderBy(x => x.UnitsInStock)
.ToList();

// Results will be sorted by the 'UnitsInStock' value in ascending order,
// with smaller values listed first.

Ordering Type:

  • By default, the OrderBy methods will determine the OrderingType from the property path expression
    and specify that ordering type in the generated RQL that is sent to the server.

  • E.g. in the above example, ordering by x => x.UnitsInStock will result in OrderingType.Long
    because that property data type is an integer.

  • Different ordering can be forced - see Force ordering type below.

Order by score

  • When querying with some filtering conditions, a basic score is calculated for each item in the results
    by the underlying indexing engine. (Read more about Lucene scoring here).

  • The higher the score value the better the match.

  • Use OrderByScore or OrderByScoreDescending to order by this score.

List<Product> products = session
.Query<Product>()
// Apply filtering
.Where(x => x.UnitsInStock < 5 || x.Discontinued)
// Call 'OrderByScore'
.OrderByScore()
.ToList();

// Results will be sorted by the score value
// with best matching documents (higher score values) listed first.

Get resulting score:

  • The score is available in the @index-score metadata property within each result.
    See how to get the resulting score from the metadata here.

  • To get the score details and see how it was calculated, you can request to include explanations in the query.
    See Include Query Explanations.

Order by random

  • Use RandomOrdering to randomize the order of the query results.

  • An optional seed parameter can be passed.

List<Product> products = session
.Query<Product>()
.Where(x => x.UnitsInStock > 10)
// Call 'Customize' with 'RandomOrdering'
.Customize(x => x.RandomOrdering())
// An optional seed can be passed, e.g.:
// .Customize(x => x.RandomOrdering('someSeed'))
.ToList();

// Results will be randomly ordered.

Order by spatial

  • If your data contains geographical locations,
    spatial query results can be sorted based on their distance from a specific point.

  • See detailed explanation in Spatial Sorting.

Order by count (aggregation query)

  • The results of a group-by query can be sorted by the Count aggregation operation used in the query.
var numberOfProductsPerCategory = session
.Query<Product>()
// Make an aggregation query
.GroupBy(x => x.Category)
.Select(x => new
{
// Group by Category
Category = x.Key,
// Count the number of product documents per category
Count = x.Count()
})
// Order by the Count value
.OrderBy(x => x.Count)
.ToList();

// Results will contain the number of Product documents per category
// ordered by that count in ascending order.

Order by sum (aggregation query)

  • The results of a group-by query can be sorted by the Sum aggregation operation used in the query.
var numberOfUnitsInStockPerCategory = session
.Query<Product>()
// Make an aggregation query
.GroupBy(x => x.Category)
.Select(x => new
{
// Group by Category
Category = x.Key,
// Sum the number of units in stock per category
Sum = x.Sum(x => x.UnitsInStock)
})
// Order by the Sum value
.OrderBy(x => x.Sum)
.ToList();

// Results will contain the total number of units in stock per category
// ordered by that number in ascending order.

Force ordering type

  • By default, the OrderBy methods will determine the OrderingType from the property path expression
    and specify that ordering type in the generated RQL that is sent to the server.

  • A different ordering can be forced by passing the ordering type explicitly to OrderBy or OrderByDescending.

  • The following ordering types are available:

    • OrderingType.Long
    • OrderingType.Double
    • OrderingType.AlphaNumeric
    • OrderingType.String (lexicographic ordering)
  • When using RQL directly, if no ordering type is specified, then the server defaults to lexicographic ordering.

Using alphanumeric ordering example:

  • When ordering mixed-character strings by the default lexicographical ordering
    then comparison is done character by character based on the Unicode values.
    For example, "Abc9" will come after "Abc10" since 9 is greater than 1.

  • If you want the digit characters to be ordered as numbers then use alphanumeric ordering
    where "Abc10" will result after "Abc9".

List<Product> products = session
.Query<Product>()
// Call 'OrderBy', order by field 'QuantityPerUnit'
// Pass a second param, requesting to order the text alphanumerically
.OrderBy(x => x.QuantityPerUnit, OrderingType.AlphaNumeric)
.ToList();
// Running the above query on the NorthWind sample data,
// would produce the following order for the QuantityPerUnit field:
// ================================================================

// "1 kg pkg."
// "1k pkg."
// "2 kg box."
// "4 - 450 g glasses"
// "5 kg pkg."
// ...

// While running with the default Lexicographical ordering would have produced:
// ============================================================================

// "1 kg pkg."
// "10 - 200 g glasses"
// "10 - 4 oz boxes"
// "10 - 500 g pkgs."
// "10 - 500 g pkgs."
// ...

Chain ordering

  • It is possible to chain multiple orderings in the query.
    Any combination of secondary sorting is possible as the fields are indexed independently of one another.

  • There is no limit on the number of sorting actions that can be chained.

  • This is achieved by using the ThenBy (ThenByDescending) and ThenByScore (ThenByScoreDescending) methods.

List<Product> products = session
.Query<Product>()
.Where(x => x.UnitsInStock > 10)
// Apply the primary sort by 'UnitsInStock'
.OrderByDescending(x => x.UnitsInStock)
// Apply a secondary sort by the score (for products with the same # of units in stock)
.ThenByScore()
// Apply another sort by 'Name' (for products with same # of units in stock and same score)
.ThenBy(x => x.Name)
.ToList();

// Results will be sorted by the 'UnitsInStock' value (descending),
// then by score,
// and then by 'Name' (ascending).

Custom sorters

  • The Lucene indexing engine allows you to create your own custom sorters.
    Custom sorters can be deployed to the server by either:

  • Once the custom sorter is deployed, you can sort the query results with it.

List<Product> products = session
.Query<Product>()
.Where(x => x.UnitsInStock > 10)
// Order by field 'UnitsInStock', pass the name of your custom sorter class
.OrderBy(x => x.UnitsInStock, "MySorter")
.ToList();

// Results will be sorted by the 'UnitsInStock' value
// according to the logic from 'MySorter' class

Syntax

// OrderBy overloads:
IOrderedQueryable<T> OrderBy<T>(string path, OrderingType ordering);
IOrderedQueryable<T> OrderBy<T>(Expression<Func<T, object>> path, OrderingType ordering);
IOrderedQueryable<T> OrderBy<T>(string path, string sorterName);
IOrderedQueryable<T> OrderBy<T>(Expression<Func<T, object>> path, string sorterName);

// OrderByDescending overloads:
IOrderedQueryable<T> OrderByDescending<T>(string path, OrderingType ordering);
IOrderedQueryable<T> OrderByDescending<T>(Expression<Func<T, object>> path, OrderingType ordering);
IOrderedQueryable<T> OrderByDescending<T>(string path, string sorterName);
IOrderedQueryable<T> OrderByDescending<T>(Expression<Func<T, object>> path, string sorterName);
ParameterTypeDescription
pathstringThe name of the field to sort by
pathExpression<Func<T, object>>A lambda expression to the field by which to sort
orderingQueryStatisticsThe ordering type that will be used to sort the results:
OrderingType.Long
OrderingType.Double
OrderingType.AlphaNumeric
OrderingType.String (default)
sorterNamestringThe name of your custom sorter class