Field Sort
Field sort allows you to sort documents based on values in a specific field.
Basic Field Sort
To sort by a specific field in ascending order:
<?php
use Zvonchuk\Elastic\Search\Sort\SortBuilders;
$sort = SortBuilders::fieldSort('price');
Specifying Sort Order
You can specify ascending or descending order:
<?php
use Zvonchuk\Elastic\Search\Sort\SortBuilders;
use Zvonchuk\Elastic\Search\Sort\SortBuilder;
// Ascending order (default)
$ascendingSort = SortBuilders::fieldSort('price')
->order(SortBuilder::ASC);
// Descending order
$descendingSort = SortBuilders::fieldSort('created_at')
->order(SortBuilder::DESC);
Sorting by Multiple Fields
To create a multi-field sort, add multiple sort criteria to your search:
<?php
use Zvonchuk\Elastic\Search\Builder\SearchSourceBuilder;
use Zvonchuk\Elastic\Search\Sort\SortBuilders;
use Zvonchuk\Elastic\Search\Sort\SortBuilder;
$searchSource = new SearchSourceBuilder();
// First sort by category (ascending)
$searchSource->sort(SortBuilders::fieldSort('category'));
// Then by price (ascending)
$searchSource->sort(SortBuilders::fieldSort('price'));
Sorting on Text Fields
When sorting on text fields, you should typically use the keyword version:
<?php
use Zvonchuk\Elastic\Search\Sort\SortBuilders;
// Sort using the keyword field
$sort = SortBuilders::fieldSort('title.keyword');
Example: Product Search with Sorting
Here’s a complete example of a product search with field sorting:
<?php
use Zvonchuk\Elastic\Client;
use Zvonchuk\Elastic\Core\SearchRequest;
use Zvonchuk\Elastic\Search\Builder\SearchSourceBuilder;
use Zvonchuk\Elastic\Query\QueryBuilders;
use Zvonchuk\Elastic\Search\Sort\SortBuilders;
use Zvonchuk\Elastic\Search\Sort\SortBuilder;
$client = Client::getInstance(['localhost:9200']);
// Create a search for electronics products
$boolQuery = QueryBuilders::boolQuery()
->must(QueryBuilders::termQuery('category', 'electronics'))
->filter(QueryBuilders::rangeQuery('price')->lte('1000'));
$searchSource = new SearchSourceBuilder();
$searchSource->query($boolQuery);
// Sort first by price (low to high)
$searchSource->sort(
SortBuilders::fieldSort('price')->order(SortBuilder::ASC)
);
// Then by rating (high to low)
$searchSource->sort(
SortBuilders::fieldSort('rating')->order(SortBuilder::DESC)
);
// Execute the search
$request = new SearchRequest('products');
$request->source($searchSource);
$response = $client->search($request);
// Process results
echo "Electronics under $1000, sorted by price (lowest first) and then rating (highest first):\n";
foreach ($response->getHits() as $hit) {
$product = $hit['_source'];
echo "- {$product['name']}: \${$product['price']}, Rating: {$product['rating']}\n";
}
Example: Pagination with Sorting
When implementing pagination with sorting, you need to keep the sort consistent:
<?php
use Zvonchuk\Elastic\Client;
use Zvonchuk\Elastic\Core\SearchRequest;
use Zvonchuk\Elastic\Search\Builder\SearchSourceBuilder;
use Zvonchuk\Elastic\Query\QueryBuilders;
use Zvonchuk\Elastic\Search\Sort\SortBuilders;
$client = Client::getInstance(['localhost:9200']);
// Page parameters
$page = 2; // Page number (1-based)
$perPage = 10; // Items per page
// Calculate from value
$from = ($page - 1) * $perPage;
// Create search
$searchSource = new SearchSourceBuilder();
$searchSource->query(QueryBuilders::matchAllQuery());
$searchSource->size($perPage);
$searchSource->from($from);
// Add consistent sorting
$searchSource->sort(SortBuilders::fieldSort('created_at')->order('desc'));
$searchSource->sort(SortBuilders::fieldSort('_id')->order('asc')); // Tie-breaker
// Execute the search
$request = new SearchRequest('products');
$request->source($searchSource);
$response = $client->search($request);
// Display results
echo "Page $page (items " . ($from + 1) . "-" . ($from + $perPage) . "):\n";
foreach ($response->getHits() as $index => $hit) {
$itemNumber = $from + $index + 1;
echo "$itemNumber. {$hit['_source']['name']}\n";
}
Using Sort with Search After
For deep pagination, you can use the search_after parameter with sort values:
<?php
use Zvonchuk\Elastic\Client;
use Zvonchuk\Elastic\Core\SearchRequest;
use Zvonchuk\Elastic\Search\Builder\SearchSourceBuilder;
use Zvonchuk\Elastic\Query\QueryBuilders;
use Zvonchuk\Elastic\Search\Sort\SortBuilders;
$client = Client::getInstance(['localhost:9200']);
// Create search
$searchSource = new SearchSourceBuilder();
$searchSource->query(QueryBuilders::matchAllQuery());
$searchSource->size(10);
// Add consistent sorting
$searchSource->sort(SortBuilders::fieldSort('created_at')->order('desc'));
$searchSource->sort(SortBuilders::fieldSort('_id')->order('asc')); // Tie-breaker
// Add search_after from previous page's last hit
$lastSortValues = ['2023-01-15T10:30:00Z', 'product_567'];
$searchSource->searchAfter($lastSortValues);
// Execute the search
$request = new SearchRequest('products');
$request->source($searchSource);
$response = $client->search($request);
// Process and display results
foreach ($response->getHits() as $hit) {
echo "{$hit['_source']['name']} - {$hit['_source']['created_at']}\n";
// Save the sort values of the last item for the next page
$lastSortValues = $hit['sort'];
}
echo "Next page search_after values: " . json_encode($lastSortValues) . "\n";