はじめに
Elasticsearchでは、Search APIで色々検索ができます。
Scriptを使用せずとも大体の検索が可能です。
ただ、時々一筋縄ではうまく行かないようなことがあります。
例えば、特定の時間(10~11時まで)のデータを取りたい,文字列を操作してから検索をかけたい
などがあるかなぁと思います。
(↑ index作成時にHourカラムを作成すれば簡単にできますが、timestampがあるのにわざわざ作りたく無い)
データ構造
mappingが以下のような物とします。
indexがarticle
fieldがtopicとtimestamp(epoch_second)という単純な物です。
{
"article" : {
"mappings" : {
"properties" : {
"topic" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
"timestamp" : {
"type" : "date",
"format" : "epoch_second"
}
}
}
}
}
やること
時間範囲でarticleを検索する。(例 : 全データ中の10~11時のデータだけ取得する。
これは、Search APIのrangeでは実現できません。(非連続時間のため)
上記の理由から、Scriptを使用します.
実行
下記は毎日の10~11時のデータを取得するqueryです。
{
"query": {
"bool" : {
"filter" : {
"script" : {
"script" : {
"source": """
ZonedDateTime zdt = doc.timestamp.value.withZoneSameInstant(ZoneId.of('Asia/Tokyo'));
int hour = zdt.getHour();
return hour >= params['min'] && hour <= params['max'];
""",
"lang": "painless",
"params": {
"min" : 10,
"max" : 11
}
}
}
}
}
}
}
説明
paramsでsourceで使う変数を設定しています。今回の場合は、10~11時のデータを取得するので10,11が設定されています。
sourceで、painlessというスクリプトでfilter条件を指定しています。
zdtでtimestampフィールドの値を取得&TZをJSTに変更しています。
hourで何時かの情報を取得しています。
return文でhourが条件に適しているかを判断しています。