4.4. さまざまな検索条件 — Groonga v7.0.6ドキュメント

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

- English

# 4.4. さまざまな検索条件

Groongaは、JavaScriptに似た文法での条件絞込や、計算した値を用いたソートを行うことができます。また、位置情報(緯度・経度)を用いた絞込・ソートを行うことができます。

## 4.4.1. JavaScriptに似た文法での絞込・全文検索

`select` コマンドの `filter` パラメータは、レコードの検索条件を指定します。 `filter` パラメータと `query` パラメータでは、 `filter` パラメータにはJavaScriptの式に似た文法で条件を指定する点が違います。

実行例:

    select --table Site --filter "_id <= 1" --output_columns _id,_key
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         1
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ]
    #       ],
    #       [
    #         1,
    #         "http://example.org/"
    #       ]
    #     ]
    #   ]
    # ]

上記クエリの詳細をみてみましょう。 `filter` パラメータではこのように条件が指定されています:

    _id <= 1

このケースでは、 `_id` の値が1以下であるという条件に合致するレコードを返します。

また、 `&&` や `||` を使って、条件のAND・OR指定をすることもできます。

実行例:

    select --table Site --filter "_id >= 4 && _id <= 6" --output_columns _id,_key
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         3
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ]
    #       ],
    #       [
    #         4,
    #         "http://example.net/afr"
    #       ],
    #       [
    #         5,
    #         "http://example.org/aba"
    #       ],
    #       [
    #         6,
    #         "http://example.com/rab"
    #       ]
    #     ]
    #   ]
    # ]
    select --table Site --filter "_id <= 2 || _id >= 7" --output_columns _id,_key
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         5
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ]
    #       ],
    #       [
    #         1,
    #         "http://example.org/"
    #       ],
    #       [
    #         2,
    #         "http://example.net/"
    #       ],
    #       [
    #         7,
    #         "http://example.net/atv"
    #       ],
    #       [
    #         8,
    #         "http://example.org/gat"
    #       ],
    #       [
    #         9,
    #         "http://example.com/vdw"
    #       ]
    #     ]
    #   ]
    # ]

`query` パラメータと `filter` パラメータを同時に指定すると、両者の条件をともに満たすレコードが結果として返ります。

## 4.4.2. `scorer` を利用したソート

`select` コマンドの `scorer` パラメータは、 全文検索を行った結果の各レコードに対して処理を行うためのパラメータです。

`filter` パラメータと同様に、 JavaScriptの式に似た文法で様々な条件を指定することができます。

実行例:

    select --table Site --filter "true" --scorer "_score = rand()" --output_columns _id,_key,_score --sortby _score
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         9
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "_score",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         6,
    #         "http://example.com/rab",
    #         424238335
    #       ],
    #       [
    #         9,
    #         "http://example.com/vdw",
    #         596516649
    #       ],
    #       [
    #         7,
    #         "http://example.net/atv",
    #         719885386
    #       ],
    #       [
    #         2,
    #         "http://example.net/",
    #         846930886
    #       ],
    #       [
    #         8,
    #         "http://example.org/gat",
    #         1649760492
    #       ],
    #       [
    #         3,
    #         "http://example.com/",
    #         1681692777
    #       ],
    #       [
    #         4,
    #         "http://example.net/afr",
    #         1714636915
    #       ],
    #       [
    #         1,
    #         "http://example.org/",
    #         1804289383
    #       ],
    #       [
    #         5,
    #         "http://example.org/aba",
    #         1957747793
    #       ]
    #     ]
    #   ]
    # ]
    select --table Site --filter "true" --scorer "_score = rand()" --output_columns _id,_key,_score --sortby _score
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         9
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "_score",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         4,
    #         "http://example.net/afr",
    #         783368690
    #       ],
    #       [
    #         2,
    #         "http://example.net/",
    #         1025202362
    #       ],
    #       [
    #         5,
    #         "http://example.org/aba",
    #         1102520059
    #       ],
    #       [
    #         1,
    #         "http://example.org/",
    #         1189641421
    #       ],
    #       [
    #         3,
    #         "http://example.com/",
    #         1350490027
    #       ],
    #       [
    #         8,
    #         "http://example.org/gat",
    #         1365180540
    #       ],
    #       [
    #         9,
    #         "http://example.com/vdw",
    #         1540383426
    #       ],
    #       [
    #         7,
    #         "http://example.net/atv",
    #         1967513926
    #       ],
    #       [
    #         6,
    #         "http://example.com/rab",
    #         2044897763
    #       ]
    #     ]
    #   ]
    # ]

'_score'は仮想的なカラムです。全文検索のスコアが代入されています。仮想的なカラムの詳細については、 擬似カラム を参照してください。

上記のクエリでは `scorer` パラメータの条件はこのとおりです:

    _score = rand()

このケースでは、rand()という乱数を返す関数を用いて、全文検索のスコアを乱数で上書きしています。

`sortby` パラメータの条件は次のとおりです:

    _score

これは、スコア順に検索結果を昇順にソートすることを意味しています。

よって、上記のクエリは実行されるたびに検索結果の並び順がランダムに変わります。

## 4.4.3. 位置情報を用いた絞込・ソート

Groongaでは、位置情報（経緯度）を保存することができます。また、保存した経緯度を用いて絞込やソートができます。

Groongaでは位置情報を保存するためのカラムの型として、TokyoGeoPoint/WGS84GeoPointの２つの型があります。前者は日本測地系、後者は世界測地系(WGS84相当)の経緯度を保存します。

以下のようにして経緯度を指定します:

- "経度のミリ秒表記x緯度のミリ秒表記" （例: "128452975x503157902"）

- "経度のミリ秒表記,緯度のミリ秒表記" （例: "128452975,503157902"）

- "経度の度数表記x緯度の度数表記" （例: "35.6813819x139.7660839"）

- "経度の度数表記,緯度の度数表記" （例: "35.6813819,139.7660839"）

ここでは、ためしに東京駅と新宿駅とついて、世界測地系での位置情報を保存してみましょう。東京駅は緯度が35度40分52.975秒、経度が139度45分57.902秒です。新宿駅は緯度が35度41分27.316秒、経度が139度42分0.929秒です。よって、ミリ秒表記の場合はそれぞれ"128452975x503157902"/"128487316x502920929"となります。度数表記の場合はそれぞれ"35.6813819x139.7660839"/"35.6909211x139.7002581"となります。

ミリ秒表記で位置情報を登録してみましょう。

実行例:

    column_create --table Site --name location --type WGS84GeoPoint
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    load --table Site
    [
     {"_key":"http://example.org/","location":"128452975x503157902"}
     {"_key":"http://example.net/","location":"128487316x502920929"},
    ]
    # [[0, 1337566253.89858, 0.000355720520019531], 2]
    select --table Site --query "_id:1 OR _id:2" --output_columns _key,location
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         2
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "location",
    #           "WGS84GeoPoint"
    #         ]
    #       ],
    #       [
    #         "http://example.org/",
    #         "128452975x503157902"
    #       ],
    #       [
    #         "http://example.net/",
    #         "128487316x502920929"
    #       ]
    #     ]
    #   ]
    # ]

`scorer` パラメータに geo_distance を使って計算した距離を設定します。

ここでは、秋葉原駅からの距離を表示させてみましょう。世界測地系では、秋葉原駅の位置は緯度が35度41分55.259秒、経度が139度46分27.188秒です。よって、geo_distance関数に与える文字列は"128515259x503187188"となります。

実行例:

    select --table Site --query "_id:1 OR _id:2" --output_columns _key,location,_score --scorer '_score = geo_distance(location, "128515259x503187188")'
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         2
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "location",
    #           "WGS84GeoPoint"
    #         ],
    #         [
    #           "_score",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "http://example.org/",
    #         "128452975x503157902",
    #         2054
    #       ],
    #       [
    #         "http://example.net/",
    #         "128487316x502920929",
    #         6720
    #       ]
    #     ]
    #   ]
    # ]

結果から、東京駅と秋葉原駅は2054m、秋葉原駅と新宿駅は6720m離れているようです。

`geo_distance` 関数は、`_score` に値を設定することで、`sortby` パラメータによるソートでも用いることができます。

実行例:

    select --table Site --query "_id:1 OR _id:2" --output_columns _key,location,_score --scorer '_score = geo_distance(location, "128515259x503187188")' --sortby -_score
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         2
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "location",
    #           "WGS84GeoPoint"
    #         ],
    #         [
    #           "_score",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "http://example.net/",
    #         "128487316x502920929",
    #         6720
    #       ],
    #       [
    #         "http://example.org/",
    #         "128452975x503157902",
    #         2054
    #       ]
    #     ]
    #   ]
    # ]

Groongaでは、「ある地点から何m以内に存在する」といった絞込も可能です。

その場合には、 `filter` パラメータで geo_in_circle を指定します。

たとえば、秋葉原駅から5000m以内にあるレコードを検索してみましょう。

実行例:

    select --table Site --output_columns _key,location --filter 'geo_in_circle(location, "128515259x503187188", 5000)'
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         1
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "location",
    #           "WGS84GeoPoint"
    #         ]
    #       ],
    #       [
    #         "http://example.org/",
    #         "128452975x503157902"
    #       ]
    #     ]
    #   ]
    # ]

経緯度が指定の矩形領域内であるかどうかを判定する geo_in_rectangle も存在します。