`Ctrl`+`K`

# 4.11. クエリ拡張

Groongaの select コマンドは `query_expander` 引数を受付ます。これを使うとクエリ文字列を拡張することができます。

例えば、"theater"ではなく"theatre"で検索したとしましょう。クエリ拡張では"theater OR theatre"の結果を返します。このようなやりかたで検索漏れを減らせます。これはユーザーが本当にやりたかったことです。

## 4.11.1. 準備

クエリ拡張を使うには、文書を格納するテーブルと検索文字列と置換文字列のペアを格納する置換テーブルを作る必要があります。置換テーブルでは主キーが元の文字列、ShortText型のカラムが置換後の文字列をあらわします。

それでは文書テーブルと置換テーブルを作成しましょう。

実行例:

    table_create Doc TABLE_PAT_KEY ShortText
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    column_create Doc body COLUMN_SCALAR ShortText
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    table_create Term TABLE_PAT_KEY ShortText --default_tokenizer TokenBigram --normalizer NormalizerAuto
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    column_create Term Doc_body COLUMN_INDEX|WITH_POSITION Doc body
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    table_create Synonym TABLE_PAT_KEY ShortText
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    column_create Synonym body COLUMN_VECTOR ShortText
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    load --table Doc
    [
    {"_key": "001", "body": "Play all night in this theater."},
    {"_key": "002", "body": "theatre is British spelling."},
    ]
    # [[0, 1337566253.89858, 0.000355720520019531], 2]
    load --table Synonym
    [
    {"_key": "theater", "body": ["theater", "theatre"]},
    {"_key": "theatre", "body": ["theater", "theatre"]},
    ]
    # [[0, 1337566253.89858, 0.000355720520019531], 2]

このようにすると、検索漏れは起こりません。これは置換テーブルがクエリ文字列として"theater"も"theatre"のいずれも受け付けるからです。

## 4.11.2. 検索

では、準備した置換テーブルを使ってみます。まずは `query_expander` を使わずに `select` コマンドを実行してみましょう。

実行例:

    select Doc --match_columns body --query "theater"
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         1
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "body",
    #           "ShortText"
    #         ]
    #       ],
    #       [
    #         1,
    #         "001",
    #         "Play all night in this theater."
    #       ]
    #     ]
    #   ]
    # ]
    select Doc --match_columns body --query "theatre"
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         1
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "body",
    #           "ShortText"
    #         ]
    #       ],
    #       [
    #         2,
    #         "002",
    #         "theatre is British spelling."
    #       ]
    #     ]
    #   ]
    # ]

このクエリではクエリ文字列に完全に一致するレコードを返します。

では、 `query_expander` を `Synonym` テーブルの `body` カラムに対して使ってみましょう。

実行例:

    select Doc --match_columns body --query "theater" --query_expander Synonym.body
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         2
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "body",
    #           "ShortText"
    #         ]
    #       ],
    #       [
    #         1,
    #         "001",
    #         "Play all night in this theater."
    #       ],
    #       [
    #         2,
    #         "002",
    #         "theatre is British spelling."
    #       ]
    #     ]
    #   ]
    # ]
    select Doc --match_columns body --query "theatre" --query_expander Synonym.body
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         2
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "body",
    #           "ShortText"
    #         ]
    #       ],
    #       [
    #         1,
    #         "001",
    #         "Play all night in this theater."
    #       ],
    #       [
    #         2,
    #         "002",
    #         "theatre is British spelling."
    #       ]
    #     ]
    #   ]
    # ]

この場合、クエリ文字列は "theater OR theatre" へと置き換えられます。つまり、検索時に表記揺れを考慮して検索できます。