Search code examples
elasticsearchelasticsearch-php

Elasticsearch: Sort by _script using php client


Is there a way to sort by _script from php client? I haven't found a way to achieve that, but I did manage to do it from cURL.

If I do the query from cURL I can do the following and it works.

curl -X GET "localhost:9200/name/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query":{"bool":{"must":{"multi_match":{"query":"hello","type":"best_fields","fields":["title","description"],"operator":"and"}}}},
  "sort": {
    "_script": {
      "type": "number",
      "script": {
        "source": "doc[\u0027language\u0027].value == \u0027en\u0027 ? 1 : 0"
      },
      "order": "desc"
    }
  }
}

But if I do it from PHP the sort parameter is added to the query string and not to the post body. And I couldn't make it work.

First I tried:

$params = [
    'index' => self::INDEX_NAME,
    'from' => $offset,
    'size' => $pageSize,
    'body' => [],
];

$params['sort'] = ['_script' => ["script" => ["source" => "doc['language'].value == 'en' ? 1 : 0"], "type" => "number", "order" => "desc"]]

$params['body']['query']['bool']['must']['multi_match'] = [
    'query' => $query,
    'type' => 'best_fields',
    'fields' => [
        'title',
        'description',
        'subject',
    ],
    'operator' => 'and',
];


/**
 * @var ElasticResponse
 */
$response = $this->elasticClient->search($params);

$arrayResponse = $response->asArray();

And the result was: No mapping found for [Array] in order to sort on.

Then I tried to send the sort param encoded:

$params['sort'] = json_encode(['_script' => ["script" => ["source" => "doc['language'].value == 'en' ? 1 : 0"], "type" => "number", "order" => "desc"]]);

and I end up with the param in the query string and it doesn't work.

POST http://localhost:9200/index/_search?sort=%7B%22_script%22%3A%7B%22script%22%3A%7B%22source%22%3A%22doc%5B%27language%27%5D.value+%3D%3D+%27en%27+%3F+1+%3A+0%22%7D%2C%22type%22%3A%22number%22%2C%22order%22%3A%22desc%22%7D%7D

Is there any way to make it work?


Solution

  • I believe the sort should be inside the body.

    $params['body']['sort'] = [
        "_script" => [
            "script" => ["source" => "doc['language'].value == 'en' ? 1 : 0"], 
            "type" => "number",
            "order" => "desc"
        ]
    ]