正規表現ツリー Dictionary レイアウト
概要
regexp_tree Dictionary を使用すると、階層的な正規表現パターンに基づいてキーを値にマッピングできます。
これは、キーの完全一致ではなく、(たとえば、正規表現パターンにマッチさせてユーザーエージェント文字列のような文字列を分類するなど)パターンマッチによる検索に最適化されています。
YAMLRegExpTree ソースを使用した正規表現ツリー Dictionary の利用
正規表現ツリー Dictionary は、正規表現ツリーを含む YAML ファイルへのパスを指定する YAMLRegExpTree ソースを使用して、ClickHouse オープンソース版で定義されます。
Dictionary のデータソースである YAMLRegExpTree は、正規表現ツリーの構造を表します。例えば次のようになります:
この設定は、正規表現ツリーのノードのリストで構成されています。各ノードは次の構造を持ちます。
- regexp: ノードの正規表現。
- attributes: ユーザー定義の Dictionary 属性のリスト。この例では、
nameとversionの 2 つの属性があります。最初のノードは両方の属性を定義します。2 番目のノードは属性nameのみを定義します。属性versionは 2 番目のノードの子ノードによって提供されます。- 属性の値には、マッチした正規表現のキャプチャグループを参照する 後方参照 (back reference) を含めることができます。この例では、最初のノードにおける属性
versionの値は、正規表現内のキャプチャグループ(\d+[\.\d]*)への後方参照\1で構成されています。後方参照番号は 1 から 9 までで、$1または\1(1 の場合)のように記述します。後方参照は、クエリ実行中にマッチしたキャプチャグループで置き換えられます。
- 属性の値には、マッチした正規表現のキャプチャグループを参照する 後方参照 (back reference) を含めることができます。この例では、最初のノードにおける属性
- child nodes: regexp ツリーノードの子ノードのリストであり、それぞれが独自の attributes と(場合によっては)さらに子ノードを持ちます。文字列マッチングは深さ優先で行われます。ある文字列が regexp ノードにマッチした場合、Dictionary はその文字列がそのノードの子ノードにもマッチするかを確認します。マッチする場合、最も深い位置でマッチしたノードの attributes が割り当てられます。子ノードの属性は、親ノードと同名の属性を上書きします。YAML ファイルにおける子ノードの名前は任意であり、上記の例では
versionsなどとできます。
Regexp ツリー Dictionary は、dictGet、dictGetOrDefault、dictGetAll 関数によるアクセスのみが可能です。例:
この場合、まず最上位レイヤーの 2 番目のノードで、正規表現 \d+/tclwebkit(?:\d+[\.\d]*) にマッチします。
その後、Dictionary は子ノードの探索を続け、その文字列が 3[12]/tclwebkit にもマッチすることを見つけます。
その結果、属性 name の値は(第 1 レイヤーで定義されている)Android となり、属性 version の値は(子ノードで定義されている)12 となります。
適切に作り込まれた YAML 設定ファイルを用いることで、正規表現ツリー Dictionary をユーザーエージェント文字列パーサーとして利用できます。 ClickHouse は uap-core をサポートしており、機能テスト 02504_regexp_dictionary_ua_parser でその使用方法を確認できます。
属性値の収集
複数の正規表現にマッチした場合、葉ノードの値だけでなく、マッチしたそれぞれから値を返したいことがあります。そのようなケースでは、専用の dictGetAll 関数を使用できます。あるノードが型 T の属性値を持つ場合、dictGetAll は 0 個以上の値を含む Array(T) を返します。
デフォルトでは、1 キーあたりで返されるマッチ数には上限がありません。上限は省略可能な第 4 引数として dictGetAll に渡すことができます。配列は トポロジカル順序 で格納されます。これは、子ノードが親ノードより前に来て、兄弟ノードはソース内の順序に従うことを意味します。
例:
結果:
マッチングモード
パターンマッチングの挙動は、特定の Dictionary 設定によって変更できます。
regexp_dict_flag_case_insensitive: 大文字・小文字を区別しないマッチングを使用します(デフォルトはfalse)。個々の式では(?i)および(?-i)で上書きできます。regexp_dict_flag_dotall: 「.」が改行文字にもマッチするようにします(デフォルトはfalse)。
ClickHouse Cloud で正規表現ツリー Dictionary を使用する
YAMLRegExpTree ソースは ClickHouse Open Source では動作しますが、ClickHouse Cloud では動作しません。
ClickHouse Cloud で regexp ツリー Dictionary を使用するには、まずローカルの ClickHouse Open Source 環境で YAML ファイルから regexp ツリー Dictionary を作成し、その後 dictionary テーブル関数と INTO OUTFILE 句を使用して、この Dictionary を CSV ファイルにエクスポートします。
CSV ファイルの内容は次のとおりです:
ダンプされたファイルのスキーマは次のとおりです。
id UInt64: RegexpTree ノードの id。parent_id UInt64: ノードの親の id。regexp String: 正規表現文字列。keys Array(String): ユーザー定義属性の名前。values Array(String): ユーザー定義属性の値。
ClickHouse Cloud で Dictionary を作成するには、まず以下のテーブル構造で regexp_dictionary_source_table テーブルを作成します。
次に、ローカルの CSV ファイルを次のように更新します
詳細については、Insert Local Files を参照してください。ソーステーブルを初期化した後、そのテーブルをソースとして RegexpTree を作成できます。