Elasticsearch のパイプラインにて
Elasticsearchのパイプライン処理にて script
Processorを使用してデータの加工などを行ってみようかと、以下のようなPainlessスクリプトを書いて・・・
int len = array?.length ?: 0;
パイプラインをPUT
したら以下のように怒られました。
lang: 'painless',
caused_by:
{ type: 'illegal_argument_exception',
reason: 'Elvis operator cannot return primitives' } },
status: 400 }
Elvis operator cannot return primitives
!!!
Elvis operator cannot return primitives
ですって!!!
いや~、マジすか?!プリミティブ型扱えないとめっちゃ不便じゃん~。。。っていうかマジすか?どうなってるの?!と不満タラタラで納得いかないのでエルビス演算子のテストケースを見てみましたよ!
以下のようになってます。
...
// Assigning to a primitive
assertCannotReturnPrimitive("int i = params.a ?: 1; return i");
assertCannotReturnPrimitive("Integer a = Integer.valueOf(1); int b = a ?: 2; return b");
assertCannotReturnPrimitive("Integer a = Integer.valueOf(1); int b = a ?: Integer.valueOf(2); return b");
assertEquals(2, exec("int i = (params.a ?: Integer.valueOf(2)).intValue(); return i"));
assertEquals(1, exec("int i = (params.a ?: Integer.valueOf(2)).intValue(); return i", singletonMap("a", 1), true));
assertEquals(1, exec("Integer a = Integer.valueOf(1); int b = (a ?: Integer.valueOf(2)).intValue(); return b"));
assertEquals(2, exec("Integer a = null; int b = (a ?: Integer.valueOf(2)).intValue(); return b"));
...
ちゃんと assertCannotReturnPrimitive
のケースが書かれてますね。。。
そしてその下では assertEquals(2
とか assertEquals(1,
とかでint型の値を扱ってるじゃないですか!
結局のところ、エルビスの後半で Integer.valueOf
のようにボックスを返してあげれば式全体が参照を返すもんだと認識されて、宜しくコンパイルしてくれるんですね。そして intValue
でプリミティブ値を取り出しています。
ちょっとめんどくさいですが、上記の方法で行けそうです。
というわけで最初の箇所は以下のように修正して無事にPUTできました。
int len = (array?.length ?: Integer.valueOf(0)).intValue();
ですがちょっと長いので以下のように修正しました。
def len = array?.length ?: Integer.valueOf(0);
後の処理で暗黙のアンボックスに期待、という方針で、今回はここでは参照型のまま受け取るということにいたしました。
う~ん、Painless
。。。