Ordering and Pagination

In the Laravel-OpenSearch integration, ordering and pagination are essential features that enable developers to manage and present data effectively. These features are designed to work seamlessly within the Laravel ecosystem, providing a familiar experience to those accustomed to Eloquent ORM.


Ordering

OpenSearch inherently ranks search results based on relevance (using internal scoring and ranking algorithms). However, it is often necessary to sort results based on specific fields. The Laravel-OpenSearch integration provides a simple and intuitive way to sort search results using the orderBy and orderByDesc methods.


OrderBy

The orderBy method allows you to specify the field by which the results should be sorted and the direction of the sort (ascending or descending). This method is straightforward and aligns with the Laravel Eloquent's orderBy functionality.

$products = Product::orderBy('status')->get();
$products = Product::orderBy('created_at', 'desc')->get();

If you have a field that is mapped as a text field with a keyword subfield, you will need to sort on the keyword subfield:

$products = Product::orderBy('name.keyword')->get();

OrderByDesc

As with Laravel's standard eloquent, the orderByDesc method is provided to quickly sort results in descending order by a specified field, without needing to explicitly set the direction.

$products = Product::orderByDesc('created_at')->get();

Offset & Limit (skip & take)

As with Eloquent, you can use the skip and take methods in your query.

$products = Product::skip(10)->take(5)->get();

Pagination

Pagination works as expected in this Laravel-OpenSearch integration.

$products = Product::where('is_active',true)
$products = $products->paginate(50)

Pagination links (Blade)

{{ $products->appends(request()->query())->links() }}

Extending ordering for OpenSearch features

The orderBy and orderByDesc methods are designed to be Laravel native, but they can be extended to support more advanced OpenSearch features.

Full parameter scope:

  • orderBy($field, $direction = 'asc', $mode = 'min', $missing = '_last')
  • orderByDesc($field, $mode = 'min', $missing = '_last')

$mode

The mode parameter allows you to specify how OpenSearch should handle sorting when multiple documents have the same value for the field being sorted. Options: min, max, sum, avg, median

Default: min when sorting in ascending order, max when sorting in descending order.

$missing

Default: _last

The missing parameter allows you to specify how OpenSearch should handle sorting when a document is missing the field being sorted. Options: _first, _last, or a custom value.

Example with mode:

// pricing_history is an array of prices ex: [9.99, 15.50, 29, 20.50]
$products = Product::where('is_active',true)->orderBy('pricing_history', 'desc', 'avg')->get();

Example with missing:

$products = Product::where('is_active',true)->orderBy('color.keyword', 'desc', null, '_first')->get();

OrderBy Geo Distance

The orderByGeo method is a specialized method for sorting by geo distance. This sorting method only works with geo fields and can be used to sort results based on their distance from a specified point.

Parameter scope:

  • orderByGeo(string $column, array $pin, $direction = 'asc', $unit = 'km', $mode = null, $type = 'arc')
  • orderByGeoDesc(string $column, array $pin, $unit = 'km', $mode = null, $type = 'arc')

$pin

The point(s) from which to calculate the distance. This can be a single point or an array of points.

  • A point is an array with two values: [lon, lat] (longitude, latitude) - Order matters and OpenSearch does not use the standard [lat, lon] format
  • For multiple points, use an array of points: [[lon1, lat1], [lon2, lat2], ...]
  • You can also specify the lat and lon keys: ['lat' => 51.50853, 'lon' => -0.12574]

$direction

  • The direction in which to sort the results. Options: asc, desc
  • asc sorts by shortest distance from the pin
  • desc sorts by longest distance from the pin

$unit

The unit to use when computing sort values. Options: m, km, mi, yd, ft

$mode

  • Used for when a field has several geo points. By default, the shortest distance is used when sorting in ascending order and the longest distance when sorting in descending order.
  • Options: min, max, sum, avg, median

$type

  • The type of distance calculation to use.
  • Options: arc, plane
  • Note: plane is faster, but inaccurate on long distances and close to the poles.
// Lat:51.50853 & Lon:-0.12574 (London)
return Product::where('is_active',true)->orderByGeo('manufacturer.location', [-0.12574, 51.50853])->get();
// OR
return Product::where('is_active',true)->orderByGeo('manufacturer.location', ['lat' => 51.50853, 'lon' => -0.12574])->get();
// Lat:48.85341 & Lon:2.3488 (Paris)
// Lat:51.50853 & Lon:-0.12574 (London)
return Product::where('is_active',true)->orderByGeo('manufacturer.location', [[2.3488, 48.85341], [-0.12574, 51.50853]], 'desc', 'km', 'avg', 'plane')->get();
//Or
return Product::where('is_active',true)->orderByGeo('manufacturer.location', [['lat' => 48.85341, 'lon' => 2.3488], ['lat' => 51.50853, 'lon' => -0.12574]], 'desc', 'km', 'avg', 'plane')->get();

Other sorting options include:

  • orderByNested

Was this page helpful?