結論、あまりよいやり方に思えないが、とりあえずやりたいことはできたので書き残しておく
概要
ElasticSearchの一つのドキュメントの中に画像URLが複数格納された配列のフィールドがあったとする
... images: [ "http://some-site/path/to/image/aaaaa.png, "http://some-site/path/to/image/bbbb.png, "http://some-site/path/to/image/cccc.png, "http://some-site/path/to/image/dddd.png, "http://some-site/path/to/image/ffff.png, ... ],
この時、特に上限を設けずに格納(例えば数十件格納)していた場合、このドキュメントを取得しようとするとレスポンスのサイズが膨大になってしまう(画像URLのパスはとても長いことが多いので特に)
しかも、取得したものの、使用する側で2要素分だけでよい場合はそのほとんどが無駄になってしまう
そこで、指定した要素数だけ取得する方法を探ってみた
対応案:script_fields を使う
script_fields
はフィールドの値をつかった計算結果を別の新しいフィールドとして定義することのできる機能
この機能を使ってimages
の2要素分を抜き出して別のフィールドとして定義すればよいのでは?
と考えたが綺麗にできず、、
以下のようなスクリプトになってしまった
{ "script_fields": { "images": { "script": { "source": """ def arr = []; def _0 = doc['images'][0]; def _1 = doc['images'][1]; if (_0 != "") { arr = [_0]; } if (_1 != "") { arr = [_0, _1]; } return arr; """ } } } }
考えたけどできなかったこと
slice
JavaScriptのsliceのような関数で doc['images'].slice(0, 2)
を考えたけどそんな機能はなかった
for文ループ
2要素なら我慢ができるが、要素数が増えたら大変なので for文を考えたが、2つの点であきらめた
- ループするごとにインクリメントされる変数
i
に対して、
doc['images'][i]
と記述するとシンタックスエラーになる - ループ内で配列に要素を格納する(
push
する)方法がわからない
+=
でもダメだった
わかればループを使いたい
まとめ
ここまでして、取得する要素数を絞るべきかは悩ましいのでレスポンスサイズがボトルネックになったら考える