1

エラスティック検索でメトリック名のインデックスを作成しています。メトリック名の形式はfoo.bar.baz.auxです。私が使っているインデックスはこちらです。

{
    "index": {
        "analysis": {
            "analyzer": {
                "prefix-test-analyzer": {
                    "filter": "dotted",
                    "tokenizer": "prefix-test-tokenizer",
                    "type": "custom"
                }
            },
            "filter": {
                "dotted": {
                    "patterns": [
                        "([^.]+)"
                    ],
                    "type": "pattern_capture"
                }
            },
            "tokenizer": {
                "prefix-test-tokenizer": {
                    "delimiter": ".",
                    "type": "path_hierarchy"
                }
            }
        }
    }
}

{
    "metrics": {
        "_routing": {
            "required": true
        },
        "properties": {
            "tenantId": {
                "type": "string",
                "index": "not_analyzed"
            },
            "unit": {
                "type": "string",
                "index": "not_analyzed"
            },
            "metric_name": {
                "index_analyzer": "prefix-test-analyzer",
                "search_analyzer": "keyword",
                "type": "string"
            }
        }
    }
}

上記のインデックスは、メトリック名に対して次の用語を作成しますfoo.bar.baz

foo
bar
baz
foo.bar
foo.bar.baz

以下のようなメトリクスがたくさんある場合

a.b.c.d.e
a.b.c.d
a.b.m.n
x.y.z

n 番目のレベルのトークンを取得するには、クエリを作成する必要があります。上記の例では

for level = 0, I should get [a, x] 
for level = 1, with 'a' as first token I should get [b]
               with 'x' as first token I should get [y]  
for level = 2, with 'a.b' as first token I should get [c, m]

用語集を書く以外に方法が思いつきませんでした。のレベル 2 トークンを把握するためにa.b、私が思いついたクエリを次に示します。

time curl -XGET http://localhost:9200/metrics_alias/metrics/_search\?pretty\&routing\=12345 -d '{
      "size": 0,
      "query": {
        "term": {
            "tenantId": "12345"
        }
      },
      "aggs": {
          "metric_name_tokens": {
              "terms": {
                  "field" : "metric_name",
                  "include": "a[.]b[.][^.]*",
                  "execution_hint": "map",
                  "size": 0
              }
          }
      }
  }'

これにより、次のバケットが生成されます。出力を解析し、そこから [c, m] を取得します。

"buckets" : [ {
     "key" : "a.b.c",
     "doc_count" : 2
   }, {
     "key" : "a.b.m",
     "doc_count" : 1
 } ]

ここまでは順調ですね。このクエリは、ほとんどのテナントでうまく機能します (tenantId term上記のクエリに注意してください)。大量のデータ (約 1 ミル) を持つ特定のテナントでは、パフォーマンスが非常に遅くなります。すべての用語の集計には時間がかかると思います。

この種のデータに対して用語集約が正しい選択であるかどうか疑問に思っており、他の可能な種類のクエリも探しています。

4

1 に答える 1