Elasticsearchによる距離検索のアレコレ
距離検索の選択肢
Soudai Sasada
Geo-distance Query
geo_distance
クエリは指定された地点からの距離によりフィルタリングをするためのクエリです。 geo_distance
クエリはフィルターのため対象を絞り込むだけで後述するクエリと違い関連性スコアに影響を与えることはありません。一定以上の距離で検索対象を絞り込みたい場合には適切なアプローチといえます。
GET my_geoshapes/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_distance": {
"distance": "200km",
"pin.location": {
"lat": 40,
"lon": -70
}
}
}
}
}
}
一方で「距離」を軸とする場合に特定地点から直線距離での計算となる都合上、必ずしも適切とは言えないケースも存在します(たとえば賃貸物件を会社からの通勤時間を考慮して探したい場合に直線距離で対象を絞り込むよりも会社の最寄り駅からの通勤時間で絞り込めた方が適切でしょう)。
ドキュメントはこちらになります。 https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-geo-distance-query.html
Distance feature query
distance_feature
クエリは指定された点からの距離により関連性スコアを調整する
クエリです。対象は「地点」の他に「日付」も可能となります。distance_feature
クエリで使用可能なプロパティは date
、 date_nanos
、 または geo_point
型です。
distance_feature
クエリの特徴は bool
クエリの should
コンテキストで使用することでこれによりドキュメントの関連性スコアに影響を与えることができます。計算式は次のとおりです。
relevance score = boost * pivot / (pivot + distance)
関連性スコアを直接boostさせるため距離が検索結果にとって重要なファクターとなる場合に有効です。またフィルタリングと違い絶対値で対象を不必要に絞り込むことがなく、また、ドキュメントの順序をsort
クエリを使わずに並べ替えることができます。
GET /items/_search
{
"query": {
"bool": {
"must": {
"match": {
"name": "chocolate"
}
},
"should": {
"distance_feature": {
"field": "location",
"pivot": "1000m",
"origin": [-71.3, 41.15]
}
}
}
}
}
sort
クエリの問題点は並べ替え指定が複数ある場合にその順序で並べ替えが適用される点にあります。
たとえば画像の有無で優先的に並び替えを行おうとすると検索ワードとの関連性より画像があることが優先されるため画像がないけど関連性の高いドキュメントは画像があるけど関連性が低いドキュメントより後に並ぶことになります。一方で関連性スコアを優先すると画像の有無は考慮されず検索ワードとの関連性が高いドキュメントが優先され、また、関連性スコアが同じ値を返す確率は低いため画像の有無はほぼ考慮されない結果となります。
これらの特性から筆者は sort
クエリはあえて使わず関連性スコアで結果を調整することが多いです。
ドキュメントはこちらになります。 https://www.elastic.co/guide/en/elasticsearch/reference/7.x/query-dsl-distance-feature-query.html
Decay Function (Function score query)
function_score
クエリはElasticsearchが提供する関数を使うことで関連性スコアを調整できるクエリですが、Decay Functionという関数では指定した地点からの距離によりスコアを減衰できます。
以下、サンプルです。
GET /_search
{
"query": {
"function_score": {
"gauss": {
"@timestamp": {
"origin": "2013-09-17",
"scale": "10d",
"offset": "5d",
"decay": 0.5
}
}
}
}
}
gauss
はスコアを減衰させる関数となります。 gauss
以外に exp
と linear
が指定でき特性が異なるので用途に合わせて使い分けることができます。ドキュメントにはそれぞれの計算式、及びスコアが減衰されるイメージが載っていてとても分かりやすいです。
ドキュメントはこちらになります。 https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html#function-decay
TODO: function_scoreでboolクエリやsortクエリが使えるか調べる
まとめ
Elasticsearchによる距離を使った検索をかんたんに調べてみました。
距離による検索を検討にあたりこのドキュメントが参考になれば幸いです。