Sort Query Results
-
When making a query, the server will return the results sorted only if explicitly requested by the query.
If no sorting method is specified when issuing the query then results will not be sorted. -
Sorting is applied by the server after the query filtering stage.
Applying filtering is recommended as it reduces the number of results RavenDB needs to sort
when querying a large dataset. -
Multiple sorting actions can be chained.
-
This article provides examples of sorting query results when making a dynamic-query.
For sorting results when querying a static-index see sort index query results. -
In this page:
Order by field value
- Use
OrderBy
orOrderByDescending
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.
List<Product> products = await asyncSession
// 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)
.ToListAsync();
// Results will be sorted by the 'UnitsInStock' value in ascending order,
// with smaller values listed first.
List<Product> products = session.Advanced
// Make a DocumentQuery on the Products collection
.DocumentQuery<Product>()
// Apply filtering (optional)
.WhereGreaterThan(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.
from "Products"
where UnitsInStock > 10
order by UnitsInStock as long
Ordering Type:
-
By default, the
OrderBy
methods will determine theOrderingType
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 inOrderingType.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
orOrderByScoreDescending
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.
List<Product> products = await asyncSession
.Query<Product>()
// Apply filtering
.Where(x => x.UnitsInStock < 5 || x.Discontinued)
// Call 'OrderByScore'
.OrderByScore()
.ToListAsync();
// Results will be sorted by the score value
// with best matching documents (higher score values) listed first.
List<Product> products = session.Advanced
.DocumentQuery<Product>()
// Apply filtering
.WhereLessThan(x => x.UnitsInStock, 5)
.OrElse()
.WhereEquals(x => x.Discontinued, true)
// Call 'OrderByScore'
.OrderByScore()
.ToList();
// Results will be sorted by the score value
// with best matching documents (higher score values) listed first.
from "Products"
where UnitsInStock < 5 or Discontinued == true
order by score()
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.
List<Product> products = await asyncSession
.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'))
.ToListAsync();
// Results will be randomly ordered.
List<Product> products = session.Advanced
.DocumentQuery<Product>()
.WhereGreaterThan(x => x.UnitsInStock, 10)
// Call 'RandomOrdering'
.RandomOrdering()
// An optional seed can be passed, e.g.:
// .RandomOrdering('someSeed')
.ToList();
// Results will be randomly ordered.
from "Products"
where UnitsInStock > 10
order by random()
// order by random(someSeed)
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.
var numberOfProductsPerCategory = await asyncSession
.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)
.ToListAsync();
// Results will contain the number of Product documents per category
// ordered by that count in ascending order.
var numberOfProductsPerCategory = session.Advanced
.DocumentQuery<Product>()
// Group by Category
.GroupBy("Category")
.SelectKey("Category")
// Count the number of product documents per category
.SelectCount()
// Order by the Count value
// Here you need to specify the ordering type explicitly
.OrderBy("Count", OrderingType.Long)
.ToList();
// Results will contain the number of Product documents per category
// ordered by that count in ascending order.
from "Products"
group by Category
order by count() as long
select key() as "Category", count()
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.
var numberOfUnitsInStockPerCategory = await asyncSession
.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)
.ToListAsync();
// Results will contain the total number of units in stock per category
// ordered by that number in ascending order.
var numberOfUnitsInStockPerCategory = session.Advanced
.DocumentQuery<Product>()
// Group by Category
.GroupBy("Category")
.SelectKey("Category")
// Sum the number of units in stock per category
.SelectSum(new GroupByField
{
FieldName = "UnitsInStock",
ProjectedName = "Sum"
})
// Order by the Sum value
// Here you need to specify the ordering type explicitly
.OrderBy("Sum", OrderingType.Long)
.ToList();
// Results will contain the total number of units in stock per category
// ordered by that number in ascending order.
from "Products"
group by Category
order by Sum as long
select key() as 'Category', sum(UnitsInStock) as Sum
Force ordering type
-
By default, the
OrderBy
methods will determine theOrderingType
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
orOrderByDescending
. -
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();
List<Product> products = await asyncSession
.Query<Product>()
// Call 'OrderBy', order by field 'QuantityPerUnit'
// Pass a second param, requesting to order the text alphanumerically
.OrderBy(x => x.QuantityPerUnit, OrderingType.AlphaNumeric)
.ToListAsync();
List<Product> products = session.Advanced
.DocumentQuery<Product>()
// Call 'OrderBy', order by field 'QuantityPerUnit'
// Pass a second param, requesting to order the text alphanumerically
.OrderBy(x => x.QuantityPerUnit, OrderingType.AlphaNumeric)
.ToList();
from "Products"
order by QuantityPerUnit as alphanumeric
// 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
) andThenByScore
(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).
List<Product> products = await asyncSession
.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)
.ToListAsync();
// Results will be sorted by the 'UnitsInStock' value (descending),
// then by score,
// and then by 'Name' (ascending).
List<Product> products = session.Advanced
.DocumentQuery<Product>()
.WhereGreaterThan(x => x.UnitsInStock, 10)
// Apply the primary sort by 'UnitsInStock'
.OrderByDescending(x => x.UnitsInStock)
// Apply a secondary sort by the score
.OrderByScore()
// Apply another sort by 'Name'
.OrderBy(x => x.Name)
.ToList();
// Results will be sorted by the 'UnitsInStock' value (descending),
// then by score,
// and then by 'Name' (ascending).
from "Products"
where UnitsInStock > 10
order by UnitsInStock as long desc, score(), Name
Custom sorters
-
The Lucene indexing engine allows you to create your own custom sorters.
Custom sorters can be deployed to the server by either:-
Sending the Put Sorters Operation from your code.
-
Uploading a custom sorter from Studio, see Custom Sorters View.
-
-
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
List<Product> products = await asyncSession
.Query<Product>()
.Where(x => x.UnitsInStock > 10)
// Order by field 'UnitsInStock', pass the name of your custom sorter class
.OrderBy(x => x.UnitsInStock, "MySorter")
.ToListAsync();
// Results will be sorted by the 'UnitsInStock' value
// according to the logic from 'MySorter' class
List<Product> products = session.Advanced
.DocumentQuery<Product>()
.WhereGreaterThan(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
from "Products"
where UnitsInStock > 10
order by custom(UnitsInStock, "MySorter")
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);
Parameter | Type | Description |
---|---|---|
path | string |
The name of the field to sort by |
path | Expression<Func<T, object>> |
A lambda expression to the field by which to sort |
ordering | QueryStatistics |
The ordering type that will be used to sort the results:OrderingType.Long OrderingType.Double OrderingType.AlphaNumeric OrderingType.String (default) |
sorterName | string |
The name of your custom sorter class |