メインコンテンツへスキップ

概要

regexp_tree Dictionary では、階層的な正規表現パターンに基づいてキーを値にマッピングできます。 完全一致によるキー照合ではなく、パターン一致のルックアップ (たとえば、正規表現パターンとの照合によって user agent 文字列のような文字列を分類するケース) 向けに最適化されています。

YAMLRegExpTree ソースを使用した正規表現ツリー辞書

ClickHouse Open Sourceでは、正規表現ツリーを含む YAML ファイルへのパスを指定した YAMLRegExpTree ソースを使用して、正規表現ツリー辞書を定義します。
Query
CREATE DICTIONARY regexp_dict
(
    regexp String,
    name String,
    version String
)
PRIMARY KEY(regexp)
SOURCE(YAMLRegExpTree(PATH '/var/lib/clickhouse/user_files/regexp_tree.yaml'))
LAYOUT(regexp_tree)
...
Dictionary ソース YAMLRegExpTree は、正規表現ツリーの構造を表します。たとえば、次のとおりです。
- regexp: 'Linux/(\d+[\.\d]*).+tlinux'
  name: 'TencentOS'
  version: '\1'

- regexp: '\d+/tclwebkit(?:\d+[\.\d]*)'
  name: 'Android'
  versions:
    - regexp: '33/tclwebkit'
      version: '13'
    - regexp: '3[12]/tclwebkit'
      version: '12'
    - regexp: '30/tclwebkit'
      version: '11'
    - regexp: '29/tclwebkit'
      version: '10'
このconfigは、正規表現ツリーノードのリストで構成されています。各ノードは次の構造を持ちます。
  • regexp: ノードの正規表現。
  • 属性: ユーザー定義のDictionary 属性のリスト。この例では、nameversion の2つの属性があります。最初のノードでは両方の属性を定義しています。2番目のノードでは name 属性のみを定義しています。version 属性は、2番目のノードの子ノードによって提供されます。
    • 属性の値には、マッチした正規表現のcapture groupを参照する後方参照を含めることができます。この例では、最初のノードの version 属性の値は、正規表現内のcapture group (\d+[\.\d]*) への後方参照 \1 で構成されています。後方参照の番号は1から9までで、$1 または \1 (1番の場合) のように記述します。後方参照は、クエリの実行時にマッチしたcapture groupで置き換えられます。
  • 子ノード: regexp tree nodeの子ノードのリストです。各子ノードは、それぞれ独自の属性と、必要に応じて子ノードを持ちます。文字列のマッチングは深さ優先で行われます。文字列がregexp nodeにマッチした場合、dictionaryはその文字列がそのノードの子ノードにもマッチするかどうかを確認します。その場合、最も深い階層でマッチしたノードの属性が割り当てられます。子ノードの属性は、同じ名前の親ノードの属性を上書きします。YAMLファイル内の子ノードの名前は任意で、たとえば上記の例では versions です。
Regexp tree dictionariesでは、dictGetdictGetOrDefaultdictGetAll の各関数を使ったアクセスのみが可能です。例:
Query
SELECT dictGet('regexp_dict', ('name', 'version'), '31/tclwebkit1024');
Response
┌─dictGet('regexp_dict', ('name', 'version'), '31/tclwebkit1024')─┐
│ ('Android','12')                                                │
└─────────────────────────────────────────────────────────────────┘
この場合、まず最上位レイヤーの2 番目のノードで正規表現 \d+/tclwebkit(?:\d+[\.\d]*) に一致します。 その後、Dictionary は子ノードの探索を続け、その文字列が 3[12]/tclwebkit にも一致することを見つけます。 その結果、属性 name の値は Android (第1レイヤーで定義) となり、属性 version の値は 12 (子ノードで定義) となります。 高度な YAML 設定ファイルを使うことで、regexp tree dictionaries をユーザーエージェント文字列のパーサーとして使用できます。 ClickHouse は uap-core をサポートしており、その使用方法は functional test 02504_regexp_dictionary_ua_parser で確認できます。

属性値の収集

一致した複数の正規表現から、末端ノードの値だけでなく複数の値を返したい場合があります。そのような場合は、専用の dictGetAll 関数を使用できます。ノードが型 T の attribute 値を持つ場合、dictGetAll は 0 個以上の値を含む Array(T) を返します。 デフォルトでは、キーごとに返される一致数に上限はありません。dictGetAll には、省略可能な第 4 引数として上限を指定できます。配列には トポロジカル順序 で値が格納されます。つまり、子ノードは親ノードより前に配置され、兄弟ノードはソース内の順序に従います。 例:
CREATE DICTIONARY regexp_dict
(
    regexp String,
    tag String,
    topological_index Int64,
    captured Nullable(String),
    parent String
)
PRIMARY KEY(regexp)
SOURCE(YAMLRegExpTree(PATH '/var/lib/clickhouse/user_files/regexp_tree.yaml'))
LAYOUT(regexp_tree)
LIFETIME(0)
# /var/lib/clickhouse/user_files/regexp_tree.yaml
- regexp: 'clickhouse\.com'
  tag: 'ClickHouse'
  topological_index: 1
  paths:
    - regexp: 'clickhouse\.com/docs(.*)'
      tag: 'ClickHouse Documentation'
      topological_index: 0
      captured: '\1'
      parent: 'ClickHouse'

- regexp: '/docs(/|$)'
  tag: 'Documentation'
  topological_index: 2

- regexp: 'github.com'
  tag: 'GitHub'
  topological_index: 3
  captured: 'NULL'
Query
CREATE TABLE urls (url String) ENGINE=MergeTree ORDER BY url;
INSERT INTO urls VALUES ('clickhouse.com'), ('clickhouse.com/docs/en'), ('github.com/clickhouse/tree/master/docs');
SELECT url, dictGetAll('regexp_dict', ('tag', 'topological_index', 'captured', 'parent'), url, 2) FROM urls;
Response
┌─url────────────────────────────────────┬─dictGetAll('regexp_dict', ('tag', 'topological_index', 'captured', 'parent'), url, 2)─┐
│ clickhouse.com                         │ (['ClickHouse'],[1],[],[])                                                            │
│ clickhouse.com/docs/en                 │ (['ClickHouse Documentation','ClickHouse'],[0,1],['/en'],['ClickHouse'])              │
│ github.com/clickhouse/tree/master/docs │ (['Documentation','GitHub'],[2,3],[NULL],[])                                          │
└────────────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────────────┘

マッチングモード

パターンマッチングの動作は、特定の Dictionary 設定によって変更できます。
  • regexp_dict_flag_case_insensitive: 大文字と小文字を区別しないマッチングを使用します (デフォルトは false) 。個々の式では (?i)(?-i) を使って上書きできます。
  • regexp_dict_flag_dotall: . が改行文字にも一致するようにします (デフォルトは false) 。

ClickHouse Cloudで正規表現ツリー辞書を使用する

YAMLRegExpTree ソースはClickHouse Open Sourceでは使用できますが、ClickHouse Cloudでは使用できません。 ClickHouse Cloudで正規表現ツリー辞書を使用するには、まずClickHouse Open SourceでYAMLファイルから正規表現ツリー辞書をローカルに作成し、次に dictionary テーブル関数と INTO OUTFILE 句を使って、このDictionaryをCSVファイルにダンプします。
SELECT * FROM dictionary(regexp_dict) INTO OUTFILE('regexp_dict.csv')
CSVファイルの内容は次のとおりです:
1,0,"Linux/(\d+[\.\d]*).+tlinux","['version','name']","['\\1','TencentOS']"
2,0,"(\d+)/tclwebkit(\d+[\.\d]*)","['comment','version','name']","['test $1 and $2','$1','Android']"
3,2,"33/tclwebkit","['version']","['13']"
4,2,"3[12]/tclwebkit","['version']","['12']"
5,2,"3[12]/tclwebkit","['version']","['11']"
6,2,"3[12]/tclwebkit","['version']","['10']"
ダンプファイルのスキーマは次のとおりです。
  • id UInt64: RegexpTree ノードの ID。
  • parent_id UInt64: ノードの親の ID。
  • regexp String: 正規表現の文字列。
  • keys Array(String): ユーザー定義属性の名前。
  • values Array(String): ユーザー定義属性の値。
ClickHouse Cloud で Dictionary を作成するには、まず次のテーブル構造で regexp_dictionary_source_table テーブルを作成します。
CREATE TABLE regexp_dictionary_source_table
(
    id UInt64,
    parent_id UInt64,
    regexp String,
    keys   Array(String),
    values Array(String)
) ENGINE=Memory;
次に、ローカルのCSVを以下のように更新します
clickhouse client \
    --host MY_HOST \
    --secure \
    --password MY_PASSWORD \
    --query "
    INSERT INTO regexp_dictionary_source_table
    SELECT * FROM input ('id UInt64, parent_id UInt64, regexp String, keys Array(String), values Array(String)')
    FORMAT CSV" < regexp_dict.csv
詳しくは、ローカルファイルの挿入を参照してください。ソーステーブルを初期化した後、テーブルソースから RegexpTree を作成できます。
CREATE DICTIONARY regexp_dict
(
    regexp String,
    name String,
    version String
PRIMARY KEY(regexp)
SOURCE(CLICKHOUSE(TABLE 'regexp_dictionary_source_table'))
LIFETIME(0)
LAYOUT(regexp_tree);
最終更新日 2026年6月10日