Painlessの配列の使用方法について

painlessで以下のようなデータを扱っています。

{
    "_shards": {
        "total": 6,
        "failed": 0,
        "successful": 6,
        "skipped": 0
    },
    "hits": {
        "hits": [
            {
                "_index": "test-2021.07.20",
                "_type": "_doc",
                "_source": {
                    "response_status": "403",
                    "time_cw": "1623984183618",
                    "src_ip": "10.111.16.62",
                    "port": "443",
                },
                "_id": "H_XawnoBjxCrCBvt7vpr",
                "_score": 1
            },
            {
                "_index": "test-2021.07.20",
                "_type": "_doc",
                "_source": {
                    "response_status": "200",
                    "time_cw": "1623984201618",
                    "src_ip": "10.111.68.10",
                    "port": "443",
                },
                "_id": "IPXawnoBjxCrCBvt7vpr",
                "_score": 1
            },
            {
                "_index": "test-2021.07.20",
                "_type": "_doc",
                "_source": {
                    "response_status": "403",
                    "time_cw": "1623984183618",
                    "src_ip": "10.111.16.62",
                    "port": "443",
                },
                "_id": "JfXcwnoBjxCrCBvtX_p_",
                "_score": 1
            }
        ],
        "total": {
            "value": 3,
            "relation": "eq"
        },
        "max_score": 1
    },
    "took": 1,
    "timed_out": false
}

ドキュメント数分ループさせ、条件に一致するドキュメントのみ別の配列に入れたいです。

■実現したいこと
(script例) response_statusが403のドキュメントのみ、別の配列に入れる
int score = 0;
for (int i = 0; i < ctx.results[0].hits.hits.length; i++) {
if (ctx.results[0].hits.hits[i]._source.response_status == "403") {
★ここで「ctx.results[0].hits.hits[i]」以下を別配列に入れたい
}
}

結果、以下のみを別配列に格納し、以降の処理で使用したいです。

{
    "hits": {
        "hits": [
            {
                "_index": "test-2021.07.20",
                "_type": "_doc",
                "_source": {
                    "response_status": "403",
                    "time_cw": "1623984183618",
                    "src_ip": "10.111.16.62",
                    "port": "443",
                },
                "_id": "H_XawnoBjxCrCBvt7vpr",
                "_score": 1
            },
            {
                "_index": "test-2021.07.20",
                "_type": "_doc",
                "_source": {
                    "response_status": "403",
                    "time_cw": "1623984183618",
                    "src_ip": "10.111.16.62",
                    "port": "443",
                },
                "_id": "JfXcwnoBjxCrCBvtX_p_",
                "_score": 1
            }
        ]
}

painlessでこのような実装は可能でしょうか

@t-nakata さん、

はい、 Painless で実装可能です。 Lambda 式を使うと簡単に書くことができます。
Kibana の Painless Lab の Parameters にテスト用の JSON を貼り付け、 params で参照してから処理するサンプルコードを書いてみました。ご参考まで。

List hits = params['hits']['hits'];
List filtered = hits.stream().filter(hit -> hit['_source']['response_status'] == "403").collect(Collectors.toList());
return filtered;

Output:

[{_index=test-2021.07.20, _type=_doc, _source={src_ip=10.111.16.62, response_status=403, port=443, time_cw=1623984183618}, _id=H_XawnoBjxCrCBvt7vpr, _score=1}, {_index=test-2021.07.20, _type=_doc, _source={src_ip=10.111.16.62, response_status=403, port=443, time_cw=1623984183618}, _id=JfXcwnoBjxCrCBvtX_p_, _score=1}]

ご回答ありがとうございます。
同様のことをPainless Labで試してみたのですが、Outputで以下のエラーが発生してしまいます。理由をご教示頂けないでしょうか

{
"root_cause": [
{
"type": "x_content_parse_exception",
"reason": "[20:29] [script] failed to parse field [params]"
}
],
"type": "x_content_parse_exception",
"reason": "[20:29] [painless_execute_request] failed to parse field [script]",
"caused_by": {
"type": "x_content_parse_exception",
"reason": "[20:29] [script] failed to parse field [params]",
"caused_by": {
"type": "json_parse_exception",
"reason": "Unexpected character ('}' (code 125)): was expecting double-quote to start field name\n at [Source: (org.elasticsearch.common.bytes.AbstractBytesReference$MarkSupportingStreamInputWrapper); line: 21, column: 18]"
}
}
}

Parameters

{
    "_shards": {
        "total": 6,
        "failed": 0,
        "successful": 6,
        "skipped": 0
    },
    "hits": {
        "hits": [
            {
                "_index": "test-2021.07.20",
                "_type": "_doc",
                "_source": {
                    "response_status": "403",
                    "time_cw": "1623984183618",
                    "src_ip": "10.111.16.62",
                    "port": "443",
                },
                "_id": "H_XawnoBjxCrCBvt7vpr",
                "_score": 1
            },
            {
                "_index": "test-2021.07.20",
                "_type": "_doc",
                "_source": {
                    "response_status": "200",
                    "time_cw": "1623984201618",
                    "src_ip": "10.111.68.10",
                    "port": "443",
                },
                "_id": "IPXawnoBjxCrCBvt7vpr",
                "_score": 1
            },
            {
                "_index": "test-2021.07.20",
                "_type": "_doc",
                "_source": {
                    "response_status": "403",
                    "time_cw": "1623984183618",
                    "src_ip": "10.111.16.62",
                    "port": "443",
                },
                "_id": "JfXcwnoBjxCrCBvtX_p_",
                "_score": 1
            }
        ],
        "total": {
            "value": 3,
            "relation": "eq"
        },
        "max_score": 1
    },
    "took": 1,
    "timed_out": false
}

ソース

List hits = params['hits']['hits'];

List filtered = hits.stream().filter(hit -> hit['_source']['response_status'] == "403").collect(Collectors.toList());

return filtered;

すみません、解決しました

度々申し訳ございません。ご教示頂いたソースについて追加で教えてください

List filtered = hits.stream().filter(hit -> hit['_source']['response_status'] == "403").collect(Collectors.toList());

比較対象の「403」を配列に格納し、比較したいです。
例えば、別途、以下のような配列を定義し、
List states = [200,400,403];

「403」部分を定数と比較するのでなく、states配列をループして200,400,403とそれぞれ比較したいです。(ループが二重になるイメージです)
このような記載は出来るのでしょうか?

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.