groonga - オープンソースのカラムストア機能付き全文検索エンジン

4.11. クエリ拡張

groongaでは、 select コマンドにquery_expansionパラメータを指定することによって、ユーザが指定した検索文字列を適宜拡張することが可能です。

たとえば、ユーザが'シークヮーサー'という文字列で検索した場合に、'シークヮーサー OR シークァーサー'で検索した場合と同一の結果を返すことによって、本来ユーザが必要とする結果をよりもれなく検索できるようになります。

4.11.1. 準備

クエリ拡張機能を使用するためには、検索対象となる文書を格納するテーブル(ここでは文書テーブルと呼びます)以外に、ユーザの指定した検索文字列を置換するためのテーブル(ここでは置換テーブルと呼びます)を準備します。置換テーブルでは、その主キーが置換前の文字列となり、文字列型(ShortText)のカラムの値が置換後の文字列となります。

TODO: 文字列型のベクターカラムでも可能であり、その場合は各要素をORでつなげたものに置換されるということを記述する。

実際に文書テーブルと置換テーブルを作成してみましょう。

実行例:

> table_create Doc TABLE_PAT_KEY ShortText
[[0,1335519662.68773,0.000400543212890625],true]
> column_create Doc body COLUMN_SCALAR ShortText
[[0,1335519662.88919,0.000899314880371094],true]
> table_create Term TABLE_PAT_KEY|KEY_NORMALIZE ShortText --default_tokenizer TokenBigram
[[0,1335519663.09089,0.000370979309082031],true]
> column_create Term Doc_body COLUMN_INDEX|WITH_POSITION Doc body
[[0,1335519663.29217,0.00676441192626953],true]
> table_create Synonym TABLE_PAT_KEY ShortText
[[0,1335519663.4998,0.000351667404174805],true]
> column_create Synonym body COLUMN_SCALAR ShortText
[[0,1335519663.70094,0.000846624374389648],true]
> load --table Doc
> [
> {"_key": "001", "body": "すっぱいブドウと甘いシークァーサー"},
> {"_key": "002", "body": "シークヮーサージュースとゴーヤチャンプル"},
> ]
[[0,1335519663.90262,0.801640033721924],2]
> load --table Synonym
> [
> {"_key": "シークァーサー", "body": "(シークァーサー OR シークヮーサー)"},
> {"_key": "シークヮーサー", "body": "(シークァーサー OR シークヮーサー)"},
> ]
[[0,1335519664.905,0.801484823226929],2]

この例では、ユーザが"シークァーサー"と入力しても、"シークヮーサー"と入力しても、それぞれの異なる表記の文書をもれなく検索するための置換テーブルを作成しています。

4.11.2. 検索

それでは実際に、準備した置換テーブルを使ってみましょう。まずは、query_expansionパラメータを指定せずにselectコマンドを使って検索してみます。

実行例:

> select Doc --match_columns body --query "シークァーサー"
[
  [
    0,
    1335519665.90753,
    0.000537633895874023
  ],
  [
    [
      [
        1
      ],
      [
        [
          "_id",
          "UInt32"
        ],
        [
          "_key",
          "ShortText"
        ],
        [
          "body",
          "ShortText"
        ]
      ],
      [
        1,
        "001",
        "すっぱいブドウと甘いシークァーサー"
      ]
    ]
  ]
]
> select Doc --match_columns body --query "シークヮーサー"
[
  [
    0,
    1335519666.10912,
    0.000688791275024414
  ],
  [
    [
      [
        1
      ],
      [
        [
          "_id",
          "UInt32"
        ],
        [
          "_key",
          "ShortText"
        ],
        [
          "body",
          "ShortText"
        ]
      ],
      [
        2,
        "002",
        "シークヮーサージュースとゴーヤチャンプル"
      ]
    ]
  ]
]

指定された文字列に完全に一致するレコードのみがそれぞれヒットします。次に、query_expansionパラメータに、準備したSynonymテーブルのbodyカラムを指定してみましょう。

実行例:

> select Doc --match_columns body --query "シークァーサー" --query_expansion Synonym.body
[
  [
    0,
    1335519666.31137,
    0.000792741775512695
  ],
  [
    [
      [
        2
      ],
      [
        [
          "_id",
          "UInt32"
        ],
        [
          "_key",
          "ShortText"
        ],
        [
          "body",
          "ShortText"
        ]
      ],
      [
        1,
        "001",
        "すっぱいブドウと甘いシークァーサー"
      ],
      [
        2,
        "002",
        "シークヮーサージュースとゴーヤチャンプル"
      ]
    ]
  ]
]
> select Doc --match_columns body --query "シークヮーサー" --query_expansion Synonym.body
[
  [
    0,
    1335519666.51486,
    0.000669717788696289
  ],
  [
    [
      [
        2
      ],
      [
        [
          "_id",
          "UInt32"
        ],
        [
          "_key",
          "ShortText"
        ],
        [
          "body",
          "ShortText"
        ]
      ],
      [
        1,
        "001",
        "すっぱいブドウと甘いシークァーサー"
      ],
      [
        2,
        "002",
        "シークヮーサージュースとゴーヤチャンプル"
      ]
    ]
  ]
]

どちらのクエリ文字列も、"(シークァーサー OR シークヮーサー)"という文字列に置換されてから検索されるため、表記の揺れを吸収して検索できるようになりました。

目次

前のトピックへ

4.10. マイクロブログ検索システムの作成

次のトピックへ

5. サジェスト

このページ