How do I create a custom sort order for the listings pages?
When you set the sort get parameter in a listing pages url (e.g. ?sort=name-az), a method is called on the\Aero\Search\Elastic\Query\Builder class (for name-az the method sortByNameAz is called).
You can find the default sort by methods in the Aero\Search\Elastic\Concerns\CanBeSorted trait.
To add a custom sort to the listings page you therefore just need to macro a method to the \Aero\Search\Elastic\Query\Builder class using the correct naming convention.
For example, we will add a summary sort:
\Aero\Search\Elastic\Documents\ListingDocument::add('string-sort', function (\Aero\Search\Elastic\Documents\ListingDocument $document) {
return [
'summary' => $document->getModel()->product->getTranslation('summary', $document->getLanguage()),
];
});
\Aero\Search\Elastic\Query\Builder::macro('sortBySummaryAz', function () {
$this->query->addSort([
'string-sort.summary' => [
'order' => 'asc',
],
]);
});
\Aero\Search\Elastic\Query\Builder::macro('sortBySummaryZa', function () {
$this->query->addSort([
'string-sort.summary' => [
'order' => 'desc',
],
]);
});
You must run php artisan aero:search:reindex --type=listing for these document changes to be applied to existing listings.
You can add these as selectable options in the sort-by dropdown on the listings page via the search settings sort_by_options.
Advanced Query
It’s possible to do a more advanced query for your Elasticsearch sort by. You can make use of Elasticsearch’s Painless scripting language
For example, you can add a sort that will execute Java to randomly sort listings:
\Aero\Search\Elastic\Query\Builder::macro('sortByRand', function () {
$this->query->addSort([
'_script' => [
'type' => 'number',
'script' => [
'lang' => \Elastica\Script\Script::LANG_PAINLESS,
'source' => $this->loadJavaFile(__DIR__.'/../scripts/random-sort.java'),
'params' => $this->parameters,
],
'order' => 'asc',
],
]);
});
// random-sort.java
def sorts = new ArrayList();
Random rand = new Random();
sorts.add(rand.nextInt(1000000));
if (sorts.size() === 0) {
sorts.add(0);
}
Collections.min(sorts.stream().map(Double::doubleToRawLongBits).collect(Collectors.toList()));