LoginSignup
4
2

More than 1 year has passed since last update.

match_phrase_prefix クエリを使ってみた

Posted at

はじめに

社内で行なっている勉強会で、Elasticsearchのmatch_phrase_prefixクエリに触れる機会があり、自分でも調べてみようと思いましたが日本語で説明された情報が少なかったため、自分なり調べてみました。match_phrase_prefixクエリの利用検討時に本記事がお役に立てれば嬉しいです。
間違えや気になる点などについてはご指摘いただけるとありがたいです。

目次

  • 環境
  • 公式ドキュメント
  • 検証データの準備
  • 検索してみる

環境

検証に利用した環境は、Elasticsearch 8.5.3です。
こちらのdocker imageを利用しました。

公式ドキュメント

match_phrase_prefixクエリについて書かれた公式ドキュメント(8.5系)はこちらです。

match_phrase_prefixクエリとは

簡単に説明すると、検索に指定された単語と同じ並び順で単語を含むドキュメント返します。このとき指定された最後の単語は前方一致として扱われ、その単語で始まる単語に一致するかどうかを判定しています。

本記事では、slopmax_expansionsパラメータについて検証データを用いて検証したいと思います。

パラメータ 説明
slop 一致する単語の間の最大単語数。デフォルト値は0。単語間の順序の逆転を考慮する場合はプラス2する。
max_expansions クエリに指定された最後の単語を前方一致でターム辞書から取得する最大値。

検証データの準備

検証データの準備するために、まずはCreate index APIを利用しindexを作成します。利用するindexはmy-index-1221です。

# index確認
GET /_cat/indices
# すでに存在する場合は削除する
DELETE my-index-1221

# index作成
PUT /my-index-1221
{
  "settings": {
    "number_of_shards": 1
  },
  "mappings": {
    "properties": {
      "title": {
          "type": "text"
      }
    }
  }
}

次にBulk APIでインデクシングします。
検索にヒットしたときの検証がやり易いように、少々違和感があるデータですがご了承ください。

POST /my-index-1221/_bulk
{ "index": { "_id": 1 }}
{ "title": "Tops Tshirt" }
{ "index": { "_id": 2 }}
{ "title": "Tops Tshirt long sleeve casual" }
{ "index": { "_id": 3 }}
{ "title": "Tops Tshirt short sleeve california" }
{ "index": { "_id": 4 }}
{ "title": "Tops Tshirt no sleeve canada" }

検索してみる

まずは単純にtops tshirtで検索してみます。
インデクシングした4件全てヒットしました。

# 4件ヒットする
GET /my-index-1221/_search
{
   "query": {
    "match_phrase_prefix" : {
        "title" : "tops tshirt"
    }
   }
}

slop:1の場合

slop:1の場合、topsとsleeveの最大単語数が1のためヒットしません。

GET /my-index-1221/_search
{
"query": {
  "match_phrase_prefix" : {
    "title" : {
      "query":"tops sleeve",
      "slop":1
    }
  }
 }
}

slop:2の場合

slop:2の場合、topsとsleeveの最大単語数が2のため3件ヒットします。

GET /my-index-1221/_search
{
"query": {
  "match_phrase_prefix" : {
    "title" : {
      "query":"tops sleeve",
      "slop":2
    }
  }
 }
}

単語をひっくり返す

クエリに指定した単語をひっくり返すとヒットするでしょうか?

GET /my-index-1221/_search
{
"query": {
  "match_phrase_prefix" : {
    "title" : {
      "query":"sleeve tops",
      "slop":2
    }
  }
 }
}

ヒットしません。

これはクエリに指定した単語をひっくり返した順序でもヒットさせたい場合は、公式ドキュメントに記載のTransposed terms have a slop of 2.を考慮する必要があります。つまりslopに指定の値をプラス2する必要があるのです。こちらのYouTubeも参考になります。

そのためslop:4で検索をするとヒットするようになります。

GET /my-index-1221/_search
{
"query": {
  "match_phrase_prefix" : {
    "title" : {
      "query":"sleeve tops",
      "slop":4   <-- 2ではなくて4を指定する
    }
  }
 }
}

最終単語で前方一致する

ここではcaという単語を前方一致させ、ターム辞書(※)に登録されているcasualcaliforniacanadaを前方一致で取得し、アルファベット順の先頭2つ(max_expansions:2)で検索を行います。

# caのワイルドカードをmax_expansionsで制御する。2ワードに制御する
GET /my-index-1221/_search
{
"query": {
  "match_phrase_prefix" : {
    "title" : {
      "query":"tops sleeve ca",
      "slop":2,
      "max_expansions": 2
    }
  }
 }
}

2件ヒットしました。

    "hits": [
      {
        "_index": "my-index-1221",
        "_id": "3",
        "_score": 1.2760415,
        "_source": {
          "title": "Tops Tshirt short sleeve california"
        }
      },
      {
        "_index": "my-index-1221",
        "_id": "4",
        "_score": 1.2760415,
        "_source": {
          "title": "Tops Tshirt no sleeve canada"
        }
      }
    ]

※転置インデックスに登録されている単語の一覧を指す。ターム辞書のイメージは下記です。

ターム辞書
california
canada
casual

まとめ

match_phrase_prefixクエリについて、公式ドキュメントを参考に動作を検証してみました。前方一致で検索できるので何かしらで利用できそうだなというイメージを持ちつつも、日本語で利用する場合は形態素解析した単語になるので、いろいろ検証が必要になりそうですね。

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2