@harue さん、
なかなか難しいですね、Data Tableでの実現方法は思いつきませんでした。できないと思います。ちょっとデータテーブルとは表示結果が異なりますが、Vegaならやりたいことはできそうです。ご参考になれば幸いです。
まず、こちらは 次のデータセットで試しました:
POST forum_237414/_bulk
{"index":{"_id":"1"}}
{"name":"A","time":"2020-01-01T10:00:00+09:00"}
{"index":{"_id":"2"}}
{"name":"A","time":"2020-01-01T20:00:00+09:00"}
{"index":{"_id":"3"}}
{"name":"A","time":"2020-02-01T10:00:00+09:00"}
{"index":{"_id":"4"}}
{"name":"A","time":"2020-02-01T20:00:00+09:00"}
{"index":{"_id":"5"}}
{"name":"B","time":"2020-02-10T10:00:00+09:00"}
{"index":{"_id":"6"}}
{"name":"B","time":"2020-02-20T20:00:00+09:00"}
上記データセットを使った際のVega描画結果が以下になります。
まず、タイムピッカーで全データセットを範囲内に収めた場合です。
ここではA
, B
共に、それぞれの一番古い日付が表示できています。
次に、タイムピッカーで、A
の最も古い日付は範囲外だが、それ以外の日付は範囲内に存在するケースです。これが本質問で非表示にされたいケースだと思います。B
については最も古い日付が範囲内に収まっているので、表示されています。
今回の例では意図的にA
のレコードは描画したまま、日付のみnot found
としました。レコードを描画しないことも可能です。
データテーブルと見え方は違えど、やりたいことはこれでできるかな、と思います。あとは見せ方を調整してもう少し表っぽくみせたり、場合によってはX軸の時系列をうまく使って、表形式よりも分かりやすい可視化が可能かもしれません。
この例では以下のVega Liteスペックを書いてみました。ポイントは:
-
query
は記述せず、フィルタリングしないで全データセットを使ってoldest
アグリゲーションを実行している
- 最も古いタイムスタンプを探すのは
terms
を使う。ここで top_hits
を使ってしまうと、それ以上何もできないので
- その後、Kibana Vegaのタイムピッカーマッピング
{"%timefilter%": "min"}
とmaxを使って最終データを絞り込みます。
- 最後に、
top_hits
で該当ドキュメントを取得
- 対象外となった場合、
calculate
を使って not found
としていますが、ここで filter
を使えばレコード自体を非表示にすることも可能と思います
{
"$schema": "https://vega.github.io/schema/vega-lite/v2.json",
"title": "全日付範囲でaggしつつ結果はTimeFilterで絞る",
"data": {
"url": {
"index": "forum_237414",
"body": {
"size": 0,
"aggs": {
"by_name": {
"terms": {"field": "name.keyword", "size": 10},
"aggs": {
"oldest": {
"terms": {"size": 1, "field": "time", "order": {"_key": "asc"}},
"aggs": {
"timefilter": {
"filter": {
"range": {
"time": {
"gte": {"%timefilter%": "min"},
"lt": {"%timefilter%": "max"}
}
}
},
"aggs": {"timefiltered": {"top_hits": {"size": 1}}}
}
}
}
}
}
}
}
},
"format": {"property": "aggregations.by_name.buckets"}
},
"transform": [
{
"calculate": "datum.oldest.buckets[0].timefilter.timefiltered.hits.total.value > 0 ? datum.oldest.buckets[0].timefilter.timefiltered.hits.hits[0] : null",
"as": "timefiltered"
},
{
"calculate": "datum.timefiltered ? datum.timefiltered._source.time : 'not found'",
"as": "time"
}
],
"encoding": {
"y": {"field": "key", "type": "ordinal", "axis": {"title": "name"}}
},
"layer": [
{
"mark": {"type": "point", "filled": true, "size": 100},
"encoding": {
"x": {
"field": "oldest.buckets[0].timefilter.timefiltered.hits.hits[0]._source.time",
"type": "temporal",
"axis": {"title": false, "grid": false}
}
}
},
{"mark": "text", "encoding": {"text": {"field": "time", "type": "nominal"}}}
]
}