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.- Note: An exception to the above rule is when Boosting is involved in the query.
Learn more in Automatic score-based ordering.
- Note: An exception to the above rule is when Boosting is involved in the query.
-
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
(see below) to order the results by the specified document field.
/** @var array<Product> $products */
$products = $session
// Make a dynamic query on the Products collection
->query(Product::class)
// Apply filtering (optional)
->whereGreaterThan("UnitsInStock", 10)
// Call 'OrderBy', pass the document-field by which to order the results
->orderBy("UnitsInStock")
->toList();
// Results will be sorted by the 'UnitsInStock' value in ascending order,
// with smaller values listed first.
/** @var array<Product> $products */
$products = $session->advanced()
// Make a DocumentQuery on the Products collection
->documentQuery(Product::class)
// Apply filtering (optional)
->whereGreaterThan("UnitsInStock", 10)
// Call 'OrderBy', pass the document-field by which to order the results
->orderBy("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
UnitsInStock
will result inOrderingType::long
because this property's data type is 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
to order the query results by this score.
/** @var array<Product> $products */
$products = $session
->query(Product::class)
// Apply filtering
->whereLessThan("UnitsInStock", 5)
->orElse()
->whereEquals("Discontinued", true)
// Call 'orderByScore'
->orderByScore()
->toList();
// Results will be sorted by the score value
// with best matching documents (higher score values) listed first.
/** @var array<Product> $products */
$products = $session->advanced()
->documentQuery(Product::class)
// Apply filtering
->whereLessThan("UnitsInStock", 5)
->orElse()
->whereEquals("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 details can be retrieved by either:
-
Request to include explanations:
You can get the score details and see how it was calculated by requesting to include explanations in the query. Currently, this is only available when using Lucene as the underlying indexing engine.
Learn more in Include query explanations. -
Get score from metadata:
The score is available in theINDEX_SCORE
metadata property within each result.
The following example shows how to get the score from the metadata of the resulting entities that were loaded to the session:// Make a query: // ============= $employees = $session ->query(Employee::class) ->search("Notes", "English") ->search("Notes", "Italian") ->boost(10) ->toList(); // Get the score: // ============== // Call 'GetMetadataFor', pass an entity from the resulting employees list $metadata = $session->advanced()->getMetadataFor($employees[0]); // Score is available in the 'INDEX_SCORE' metadata property $score = $metadata[DocumentsMetadata::INDEX_SCORE];
Order by random
-
Use
randomOrdering
to randomize the order of the query results. -
An optional seed parameter can be passed.
/** @var array<Product> $products */
$products = $session->query(Product::class)
->whereGreaterThan("UnitsInStock", 10)
// Call 'randomOrdering'
->randomOrdering()
// An optional seed can be passed, e.g.:
// ->randomOrdering('someSeed')
->toList();
// Results will be randomly ordered.
/** @var array<Product> $products */
$products = $session->advanced()
->documentQuery(Product::class)
->whereGreaterThan("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.
$numberOfProductsPerCategory = $session
->query(Product::class)
// Make an aggregation query
->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.
$numberOfProductsPerCategory = $session->advanced()
->documentQuery(Product::class)
// 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.
$numberOfUnitsInStockPerCategory = $session
->query(Product::class)
// Make an aggregation query
// Group by Category
->groupBy("Category")
// Order by the Sum value
->selectKey("Category")
->selectSum(new GroupByField("UnitsInStock", "Sum"))
->orderBy("Sum")
->toList();
// Results will contain the total number of units in stock per category
// ordered by that number in ascending order.
$numberOfUnitsInStockPerCategory = $session->advanced()
->documentQuery(Product::class)
// Group by Category
->groupBy("Category")
->selectKey("Category")
// Sum the number of units in stock per category
->selectSum(new GroupByField("UnitsInStock", "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".
/** @var array<Product> $products */
$products = $session
->query(Product::class)
// Call 'OrderBy', order by field 'QuantityPerUnit'
// Pass a second param, requesting to order the text alphanumerically
->orderBy("QuantityPerUnit", OrderingType::alphaNumeric())
->toList();
/** @var array<Product> $products */
$products = $session->advanced()
->documentQuery(Product::class)
// Call 'OrderBy', order by field 'QuantityPerUnit'
// Pass a second param, requesting to order the text alphanumerically
->orderBy("QuantityPerUnit", OrderingType::alphaNumeric())
->toList();
from "Products"
order by QuantityPerUnit as alphanumeric
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.
/** @var array<Product> $products */
$products = $session
->query(Product::class)
->whereGreaterThan("UnitsInStock", 10)
// Apply the primary sort by 'UnitsInStock'
->orderByDescending("UnitsInStock")
// Apply a secondary sort by the score (for products with the same # of units in stock)
->orderByScore()
// Apply another sort by 'Name' (for products with same # of units in stock and same score)
->orderBy("Name")
->toList();
// Results will be sorted by the 'UnitsInStock' value (descending),
// then by score,
// and then by 'Name' (ascending).
/** @var array<Product> $products */
$products = $session->advanced()
->documentQuery(Product::class)
->whereGreaterThan("UnitsInStock", 10)
// Apply the primary sort by 'UnitsInStock'
->orderByDescending("UnitsInStock")
// Apply a secondary sort by the score
->orderByScore()
// Apply another sort by 'Name'
->orderBy("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.
/** @var array<Product> $products */
$products = $session
->query(Product::class)
->whereGreaterThan("UnitsInStock", 10)
// Order by field 'UnitsInStock', pass the name of your custom sorter class
->orderBy("UnitsInStock", "MySorter")
->toList();
// Results will be sorted by the 'UnitsInStock' value
// according to the logic from 'MySorter' class
/** @var array<Product> $products */
$products = $session->advanced()
->documentQuery(Product::class)
->whereGreaterThan("UnitsInStock", 10)
// Order by field 'UnitsInStock', pass the name of your custom sorter class
->orderBy("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
{code:php syntax@ClientApi\Session\Querying\SortQueryResults.php /}
Parameter | Type | Description |
---|---|---|
$field | string |
The field to sort by |
$sorterNameOrOrdering | string |
The ordering type to sort the results by:OrderingType::long OrderingType::double OrderingType::alphaNumeric OrderingType::string (default) |