ウォッチャーにおいて計算結果をフィールドとして追加する方法

(特定の文字や記号やアルファベットが含まれるとなぜかタイトルがエラーになってしまうため、わかりにくいタイトルになってしまっております。。)

ある条件を満たしたユーザのみを抽出し、ドキュメント内のフィールドから算出した結果をさらにフィールドとして追加して、メール送信を行うというWatcherを作成しようとしています。
例としては下記の通り、出力時に"打数","安打"から打率を計算し、フィールドに新たに追加して出力する、というイメージです。
このときの、打率を計算して、新たなフィールドとして追加するScriptがわからず困っております。もしご存知の方いましたら、教えていただきたいです。

◆ Watcher Input
PUT my_index/
    {
     "id":1
     "打数":5 
     "安打":1
    }
    PUT my_index/
    {
     "id":2
     "打数":4
     "安打":2
    }

◆ Watcher Condition
~割愛~

◆ Watcher Action で出力するインデックスの内容
{
 "id":1
 "打数":5 
 "安打":1 
 "打率":0.2
}
{
 "id":2
 "打数":4
 "安打":2 
 "打率":0.5 
}

こんにちわ。

以前Watcherの質問でありました内容に少し付け足せば可能かと思います。

transformでこのようにしております。
ctx.payload.hits.hits[i]['打率'] = の部分がフィールドを追加しているところになります。
(蛇足ですが、ゼロ除算、ぬるぽなどは別途考慮ください)

"actions": {
    "index_payload": {
      "transform": {
        "script": """
        for (int i = 0; i < ctx.payload.hits.hits.length; ++i) {
          ctx.payload.hits.hits[i] = ctx.payload.hits.hits[i]._source;
          ctx.payload.hits.hits[i]['打率'] = (double)ctx.payload.hits.hits[i]['安打'] / (double)ctx.payload.hits.hits[i]['打数'];
        }
        return [ '_doc' : ctx.payload.hits.hits];
        """
      },
      "index": {
        "index": "watcher-index"
      }
    }
  }

実際に登録されるindexはこのようになりました。

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "watcher-index",
        "_type" : "_doc",
        "_id" : "XXFIo2sBsZpVTu8PuMgc",
        "_score" : 1.0,
        "_source" : {
          "安打" : 2,
          "打数" : 4,
          "打率" : 0.5
        }
      },
      {
        "_index" : "watcher-index",
        "_type" : "_doc",
        "_id" : "XnFIo2sBsZpVTu8PuMgc",
        "_score" : 1.0,
        "_source" : {
          "安打" : 1,
          "打数" : 5,
          "打率" : 0.2
        }
      }
    ]
  }
}

打率が計算されて追加されていることが確認できました。

ご参考になれば幸いです。

動作確認環境: Elasticseardch 7.2.0

tsgkdtさん

丁寧でわかりやすいご説明、ありがとうございます。

ctx.payload.hits.hits[i]['打率'] = (double)ctx.payload.hits.hits[i]['安打'] / (double)ctx.payload.hits.hits[i]['打数'];

こうやってフィールドの値を用いた計算と、新たなフィールド作成ができるのですね、

重ねて恐縮ですが、
このあたりの細かい文法がわかりやすくまとまったページ等、もしご存知でしたら教えていただきたいです。

スクリプトで使用されるpainlessについての情報入手元ですが、公式サイトだと以下が参考になるかと思います。

言語についての説明
https://www.elastic.co/guide/en/elasticsearch/painless/master/painless-lang-spec.html

簡単な使用例リスト
https://www.elastic.co/guide/en/elasticsearch/painless/current/painless-walkthrough.html

painlessを使いこなせると、フィールドやスコア、reindex、ingestなどいろいろな場面で活躍できそうです。
Javaに親しみがあれば、さほど苦(pain)がないかと思います。

tsgkdtさん

ありがとうございます!やはり一番まとまっているのは公式ドキュメントですよね。

実は公式ドキュメントは拝見したのですが、基礎知識がないために、
書いてある部分についてはなんとなくわかるものの応用が利かせられない、という側面が自分の場合ありそうです、

Java,Groovyの考え方なども参考にしながら、公式ドキュメントで勉強していこうと思います、
ご丁寧にありがとうございました!

同じような悩みを持つ人が思いのほか多いと、話してみて気づくこともあります。

公式トレーニングや、コミュニティの勉強会などで同志が見つかると、独力での勉強もはかどるかと思います。

ということで、よろしければ以下もご検討ください。
公式トレーニングは9月、コミュニティの勉強会は来週10日にあります。

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