elastic / elasticsearch-php

Official PHP client for Elasticsearch.
https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/index.html
MIT License
5.26k stars 966 forks source link

Sort by _script using php client #1257

Closed khrizt closed 1 year ago

khrizt commented 1 year ago

Summary of problem or feature request

Sorting by _script from php client doesn't work or I haven't found the way to achieve that. But I managed to do this type of sorting from cURL.

I hope someone can guide me if this is a bug or am I doing something wrong.

Code snippet of problem

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 haven't managed to make it work. If I do this

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

I get the error: No mapping found for [Array] in order to sort on.

And if I try to send it encoded

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

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

System details

ezimuel commented 1 year ago

@khrizt I translated the cURL command that you reported:

$params = [
    'index' => 'name',
    'body'  => [
        'bool' => [
            'must' => [
                'multi_match' => [
                    'query' => 'hello',
                    'type' => 'best_fields'
                ],
                'fields' => [ 'title', 'description' ],
                'operator' => 'and'
            ]
        ],
        'sort' => [
            '_script' => [
                'type' => 'number',
                'script' => [
                    'source' => "doc['language'].value == 'en' ? 1 : 0"
                ],
                'order' => 'desc'
            ]
        ]
    ]
];

$results = $client->search($params);

Let me know if this works. If you are looking for other PHP examples, I suggest to have a look at https://github.com/elastic/elasticsearch-php-examples

khrizt commented 1 year ago

Hi @ezimuel, thanks a lot. It works, I don't know how variants of this I tried but none were the correct one :roll_eyes:.

Thanks!