事象
Elasticsearch (Version 6.8.5) に対して、
Elasticsearch-PHP で terms 句を含む query を作って検索(_search)を行ったところ、以下のエラーが出た。
[terms] query does not support [0] within lookup element
あるべき姿
以下のような配列を Elasticsearch の terms 句に渡した場合、
$accounts = ["aaa", "ccc"]
Elasticsearch で以下の様に扱われること。
"terms": {
"account": ["aaa", "ccc"]
}
今回のエラーが出た状況
まず、PHP で配列の真ん中を削り、添え字を歯抜けにする。
$accounts = ["aaa", "bbb", "ccc"];
unset($accounts[1]); ◆"bbb" を削る
print_r($accounts);
* 配列の添え字はこんな感じになる
Array
(
[0] => aaa
[2] => ccc
)
この配列を PHP で Elasticsearch に渡す。
$client = Elasticsearch\ClientBuilder::create()
->setHosts(["localhost:9200"])->build();
$client->search([
"index" => "test_index",
"body" => [
"query" => [
"terms" => ["account" => $accounts]
]
]
]);
すると、Elasticsearch の query としては以下の様に扱われてしまう。
"terms": {
"account": {
"0": "aaa",
"2": "bbb"
}
}
"0" などという key は terms 句の中に存在しないためエラーになっていた。
[terms] query does not support [0] within lookup element
原因まとめ
Elasticsearch-PHP を利用する場合、
body 内の配列(例:terms 句の検索値)の添え字が0から始まらない、
または途中の数字が抜けている場合、
Elasticsearch 側で Object として認識されてしまい、予期せぬエラーを産む。
解決方法
(1) おすすめの方法
Elasticsearch-PHP の body 内で配列を指定したい場合、
array_values などで配列の添え字を 0から始まる歯抜けのない数列 に揃えること。
個人的には配列利用箇所で array_values するのが楽。
(2) body には JSON 文字列を渡すこともできるので、
直接 JSON 文字列として配列を定義して渡す。
ただ、この方法を PHP で使うのはかなりめんどくさい。
Pytohn と違って {} が配列ではないためベタで query を書く必要がある。
変数展開もピリオド(.)がたくさん出てきて見づらくなる。。。
あと、json_encode でも歯抜けの配列が Object に変わってしまうので注意が必要。