テキスト アナライザを利用する

CREATE SEARCH INDEX DDL ステートメントSEARCH 関数TEXT_ANALYZE 関数は、高度なテキスト アナライザ構成オプションをサポートします。BigQuery のテキスト アナライザとそのオプションを理解することで、検索エクスペリエンスを向上させることができます。

このドキュメントでは、BigQuery で利用できるさまざまなテキスト アナライザとその構成オプションの概要や、BigQuery におけるテキスト アナライザと検索の連携の例を示します。テキスト アナライザの構文の詳細については、テキスト分析をご覧ください。

テキスト アナライザ

BigQuery は、次のテキスト アナライザをサポートしています。

  • NO_OP_ANALYZER
  • LOG_ANALYZER
  • PATTERN_ANALYZER

NO_OP_ANALYZER

正確に一致させる必要がある前処理済みのデータがある場合は、NO_OP_ANALYZER を使用してください。テキストにはトークン化も正規化も行われません。このアナライザはトークン化または正規化を行わないため、構成を受け入れません。NO_OP_ANALYZER の詳細については、NO_OP_ANALYZER をご覧ください。

LOG_ANALYZER

LOG_ANALYZER は、次の方法でデータを変更します。

  • テキストは小文字になります。
  • 127 を超える ASCII 値はそのまま保持されます。

  • テキストは、次の区切り文字でトークンと呼ばれる個別の語句に分割されます。

    [ ] < > ( ) { } | ! ; , ' " * & ? + / : = @ . - $ % \ _ \n \r \s \t %21 %26
    %2526 %3B %3b %7C %7c %20 %2B %2b %3D %3d %2520 %5D %5d %5B %5b %3A %3a %0A
    %0a %2C %2c %28 %29
    

    デフォルトの区切り文字を使用しない場合は、テキスト アナライザのオプションとして使用する特定の区切り文字を指定できます。LOG_ANALYZER を使用すると、特定の区切り文字とトークン フィルタを構成して、検索結果を詳細に制御できます。LOG_ANALYZER を使用する場合に利用できる特定の構成オプションについて詳しくは、delimiters アナライザ オプションtoken_filters アナライザ オプションをご覧ください。

PATTERN_ANALYZER

PATTERN_ANALYZER テキスト アナライザは、正規表現を使用してテキストからトークンを抽出します。PATTERN_ANALYZER と使用する正規表現エンジンと構文は RE2 です。PATTERN_ANALYZER は、次の順序でパターンをトークン化します。

  1. この関数は、文字列のパターンに一致する最初の部分文字列を(左から)見つけます。これは、出力に含まれるトークンです。
  2. 入力文字列からステップ 1 で見つかった部分文字列の最後まで、すべて削除されます。
  3. 文字列が空になるまでこのプロセスを繰り返します。

次の表に、PATTERN_ANALYZER トークンの抽出例を示します。

パターン テキストを入力する 出力トークン
ab ababab
  • ab
ab abacad
  • ab
[a-z]{2} abacad
  • ab
  • ac
  • ad
aaa aaaaa
  • aaa
[a-z]/ a/b/c/d/e
  • a/
  • b/
  • c/
  • d/
/[^/]+/ aa/bb/cc
  • /bb/
[0-9]+ abc
(?:/?)[a-z] /abc
  • /abc
(?:/)[a-z] /abc
  • /abc
(?:[0-9]abc){3}(?:[a-z]000){2} 7abc7abc7abcx000y000
  • 7abc7abc7abcx000y000
".+" "cats" と "dogs"
  • "cats" と "dogs"


最大量指定子 + を使用すると、テキスト内で可能な限り長い文字列に一致するため、'"cats" と "dogs"' がテキスト内でトークンとして抽出されます。
".+?" "cats" と "dogs"
  • "cats"
  • "dogs"


遅延量指定子 +? を使用すると、正規表現がテキスト内で可能な限り短い文字列に一致するため、'"cats"'、'"dogs"' がテキスト内で 2 つの別々のトークンとして抽出されます。

PATTERN_ANALYZER テキスト アナライザを使用すると、SEARCH 関数で使用された際にテキストから抽出されたトークンをより詳細に制御できます。次の表は、パターンと結果が異なれば、SEARCH の結果も異なることを示しています。

パターン クエリ テキスト テキストから抽出されたトークン SEARCH(text, query) 説明
abc abcdef abcghi
  • abcghi
TRUE ['abcghi'] の 'abc'
cd[a-z] abcdef abcghi
  • abcghi
FALSE ['abcghi'] の 'cde'
[a-z]/ a/b/ a/b/c/d/
  • a/
  • b/
  • c/
  • d/
TRUE ['a/', 'b/', 'c/', 'd/'] の 'a/' および ['a/', 'b/', 'c/', 'd/'] の 'b/'
/[^/]+/ aa/bb/ aa/bb/cc/
  • /bb/
TRUE ['/bb/'] の '/bb/'
/[^/]+/ bb aa/bb/cc/
  • /bb/
エラー クエリ語句に一致するものがない
[0-9]+ abc abc123 エラー クエリ語句に一致するものがない
[0-9]+ `abc` abc123 エラー クエリ語句に一致するものがない

特殊文字ではなくバッククォートとして照合。
[a-z][a-z0-9]*@google\.com メールアドレス: test@google.com test@google.com
  • test@google.com
TRUE 'test@google.com' の 'test@google.com'
abc abc\ abc abc
  • abc
TRUE ['abc'] の 'abc'

スペースがエスケープされているため、'abc abc' は検索クエリパーサーによって解析された後の単一のサブクエリです。
(?i)(?:Abc)(正規化なし) aBcd Abc
  • Abc
FALSE ['Abc'] の 'aBc'
(?i)(?:Abc)

normalization:
lower_case = true
aBcd Abc
  • abc
TRUE ['abc'] の 'abc'
(?:/?)abc bc/abc /abc/abc/
  • /abc
TRUE ['/abc'] の '/abc'
(?:/?)abc abc d/abc
  • /abc
FALSE ['/abc'] の 'abc'
".+" "cats" "cats" と "dogs"
  • "cats" と "dogs"
FALSE ['"cats" and "dogs"] の '"cats"'

最大量指定子 + を使用すると、正規表現がテキスト内で可能な限り長い文字列に一致するため、'"cats" と "dogs"' がテキスト内のトークンとして抽出されます。
".+?" "cats" "cats" と "dogs"
  • "cats"
  • "dogs"
TRUE ['"cats"', '"dogs"] の '"cats"'

遅延量指定子 +? を使用すると、正規表現がテキスト内で可能な限り短い文字列に一致するため、'"cats"'、'"dogs"' がテキスト内で 2 つの別々のトークンとして抽出されます。

以下の各例では、カスタマイズ オプションを指定してテキスト分析を使用し、検索インデックスの作成、トークンの抽出を行い、検索結果を返す場合について示します。

NFKC ICU 正規化とストップワードを指定した LOG_ANALYZER

次の例では、NFKC ICU 正規化とストップワードを指定して LOG_ANALYZER オプションを構成します。この例では、次のデータテーブルにデータが入力済みであることを前提としています。

CREATE TABLE dataset.data_table(
  text_data STRING
);

NFKC ICU 正規化とストップワードのリストを指定して検索インデックスを作成するには、CREATE SEARCH INDEX DDL ステートメントanalyzer_options オプションに JSON 形式の文字列を作成します。LOG_ANALYZER を指定して検索インデックスを作成する際に利用できるオプションの全一覧については、LOG_ANALYZER をご覧ください。この例では、ストップワードは "the", "of", "and", "for" です。

CREATE OR REPLACE SEARCH INDEX `my_index` ON `dataset.data_table`(ALL COLUMNS) OPTIONS(
  analyzer='PATTERN_ANALYZER',
  analyzer_options= '''{
    "token_filters": [
      {
        "normalizer": {
          "mode": "ICU_NORMALIZE",
          "icu_normalize_mode": "NFKC",
          "icu_case_folding": true
        }
      },
      { "stop_words": ["the", "of", "and", "for"] }
    ]
  }''');

前の例について、次の表に text_data のさまざまな値のトークンの抽出を示します。このドキュメントでは、2 つの疑問符(??)との違いを示すために、二重疑問符()を斜体にしています。

データテキスト インデックスのトークン 説明
The Quick Brown Fox ["quick", "brown", "fox"] LOG_ANALYZER トークン化により、トークン ["The", "Quick", "Brown", "Fox"] が生成されます。

次に、icu_case_folding = true を指定した ICU 正規化で、トークンが小文字に変換されて ["the", "quick", "brown", "fox"] が生成されます。

最後に、ストップワード フィルタでリストから "the" が削除されます。
The Ⓠuick Ⓑrown Ⓕox ["quick", "brown", "fox"] LOG_ANALYZER トークン化により、トークン ["The", "Ⓠuick", "Ⓑrown", "Ⓕox"] が生成されます。

次に、icu_case_folding = true を指定した NFKC ICU 正規化で、トークンが小文字に変換されて ["the", "quick", "brown", "fox"] が生成されます。

最後に、ストップワード フィルタでリストから "the" が削除されます。
ⓆuickⒻox ["quick??fox"] LOG_ANALYZER トークン化により、トークン ["The", "ⓆuickⒻox"] が生成されます。

次に、icu_case_folding = true を指定した NFKC ICU 正規化で、トークンが小文字に変換されて ["quick??fox"] が生成されます。二重疑問符の Unicode が 2 つの疑問符の ASCII 文字に正規化されていることに注意してください。

最後に、フィルタリストにはトークンが含まれていないため、ストップワード フィルタは何も行いません。

検索インデックスが作成されたため、SEARCH 関数を使用して、検索インデックスで指定された同じアナライザ構成を使用してテーブルを検索できます。SEARCH 関数内のアナライザ構成が検索インデックスの構成と一致しない場合、検索インデックスは使用されません。次のクエリを使用します。

SELECT
  SEARCH(
  analyzer => 'LOG_ANALYZER',
  analyzer_options => '''{
    "token_filters": [
      {
        "normalizer": {
          "mode": "ICU_NORMALIZE",
          "icu_normalize_mode": "NFKC",
          "icu_case_folding": true
        }
      },
      {
        "stop_words": ["the", "of", "and", "for"]
      }
    ]
  }''')

次のように置き換えます。

  • search_query: 検索するテキスト。

次の表に、さまざまな検索テキストと search_query の値に基づくさまざまな結果を示します。

text_data search_query 結果 説明
The Quick Brown Fox "Ⓠuick" TRUE テキストから抽出されたトークンの最終的なリストは ["quick", "brown", "fox"] です。
テキストクエリから抽出されたトークンの最終的なリストは ["quick"] です。

リスト クエリトークンはすべてテキスト トークンで確認できます。
The Ⓠuick Ⓑrown Ⓕox "quick" TRUE テキストから抽出されたトークンの最終的なリストは ["quick", "brown", "fox"] です。
テキストクエリから抽出されたトークンの最終的なリストは ["quick"] です。

リスト クエリトークンはすべてテキスト トークンで確認できます。
ⓆuickⒻox "quick" FALSE テキストから抽出されたトークンの最終的なリストは ["quick??fox"] です。

テキストクエリから抽出されたトークンの最終的なリストは ["quick"] です。

"quick" はテキストからのトークンのリストにありません。
ⓆuickⒻox "quickfox" TRUE テキストから抽出されたトークンの最終的なリストは ["quick??fox"] です。

テキストクエリから抽出されたトークンの最終的なリストは ["quick??fox"] です。

"quick??fox" はテキストからのトークンのリストにあります。
ⓆuickⒻox "`quickfox`" FALSE LOG_ANALYZER では、バッククォートはテキストの完全一致を必要とします。

ストップワードを指定した IPv4 検索用の PATTERN_ANALYZER

次の例では、特定のストップワードをフィルタしながら特定のパターンを検索するように、PATTERN_ANALYZER テキスト アナライザを構成しています。この例では、パターンは IPv4 アドレスと一致し、localhost 値(127.0.0.1)は無視されます。

この例では、次のテーブルにデータが入力されていることを前提としています。

CREATE TABLE dataset.data_table(
  text_data STRING
);

pattern オプションとストップワードのリストを指定して検索インデックスを作成するには、DDL ステートメント CREATE SEARCH INDEXanalyzer_options オプションに JSON 形式の文字列を作成します。PATTERN_ANALYZER を指定して検索インデックスを作成する際に利用できるオプションの全一覧については、PATTERN_ANALYZER をご覧ください。この例では、ストップワードはローカルホスト アドレス 127.0.0.1 です。

CREATE SEARCH INDEX my_index
ON dataset.data_table(text_data)
OPTIONS (analyzer = 'PATTERN_ANALYZER', analyzer_options = '''{
  "patterns": [
    "(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)[.]){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
  ],
  "token_filters": [
    {
      "stop_words": [
        "127.0.0.1"
      ]
    }
  ]
}'''
);

analyzer_options を指定して正規表現を使用する場合は、\ 記号を含む正規表現(\d\b など)を適切にエスケープするために、先頭に \ 記号を 3 つ記載します。

次の表に、text_data のさまざまな値のトークン化オプションを示します。

データテキスト インデックスのトークン 説明
abc192.168.1.1def 172.217.20.142 ["192.168.1.1", "172.217.20.142"] アドレスとテキストの間にスペースがない場合でも、IPv4 パターンは IPv4 アドレスをキャプチャします。
104.24.12.10abc 127.0.0.1 ["104.24.12.10"] "127.0.0.1" はストップワードのリストに含まれているため、除外されます。

検索インデックスが作成されたため、SEARCH 関数を使用して、analyzer_options で指定されたトークン化に基づいてテーブルを検索できます。次のクエリを使用します。

SELECT
  SEARCH(dataset.data_table.text_data
  "search_data",
  analyzer => 'PATTERN_ANALYZER',
  analyzer_options => '''{
    "patterns": [
      "(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)[.]){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
      ],
    "token_filters": [
      {
        "stop_words": [
          "127.0.0.1"
        ]
      }
    ]
  }'''
);

次のように置き換えます。

  • search_query: 検索するテキスト。

次の表に、さまざまな検索テキストと search_query の値に基づくさまざまな結果を示します。

text_data search_query 結果 説明
128.0.0.2 "127.0.0.1" エラー クエリ内に検索トークンがありません。

クエリはテキスト アナライザを通過し、"127.0.0.1" トークンが除外されます。
abc192.168.1.1def 172.217.20.142 "192.168.1.1abc" TRUE クエリから抽出されたトークンのリストは ["192.168.1.1"] です。

テキストから抽出されたトークンのリストは ["192.168.1.1", "172.217.20.142"] です。
abc192.168.1.1def 172.217.20.142 "`192.168.1.1`" TRUE クエリから抽出されたトークンのリストは ["192.168.1.1"] です。

テキストから抽出されたトークンのリストは ["192.168.1.1", "172.217.20.142"] です。

バッククォートは PATTERN_ANALYZER では通常の文字として扱われます。

次のステップ