diadia

興味があることをやってみる。自分のメモを残しておきます。

matchとmatch_phraseクエリの検索結果の違いをメモ

以下のsample1インデックスを作成し、matchやmatch_phraseを使って観察してみる。

インデックスはhtmlタグが存在している場合にタグを削除するhtml_strip, 日本語文章を日本語単語に分けるkuromoji_tokenizerを使っている。

PUT sample1
{
  "settings": {
      "analysis": {
        "analyzer": {
          "kuromoji_standard": {
            "char_filter": [
              "html_strip",
              "icu_normalizer"
            ],
            "tokenizer": "kuromoji_tokenizer",
            "type": "custom"
          }
        }
      }
  },
  "mappings":{
    "properties":{
      "content":{
        "type": "text",
        "analyzer":"kuromoji_standard"
      }
    }
  }
}

ドキュメントの登録

以下3つの文章を登録する。あとで”消費者センター”で検索をかけるための文章になっている。

PUT sample1/_doc/1
{
  "content":"私は消費者センターに連絡する"
}

PUT sample1/_doc/2
{
  "content":"カロリーを消費する"
}

PUT sample1/_doc/3
{
  "content":"消費する者はコンシューマー。中央はセンターという。"
}

また、analyzeAPIの結果では"消費者センター"の単語は以下にように分けられているを確認した。

GET sample1/_analyze
{
  "analyzer": "kuromoji_standard",
  "text":"消費者センター"
}


///////////////////////////////////// 結果 /////////////////////////////////////

{
  "tokens" : [
    {
      "token" : "消費",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "者",
      "start_offset" : 2,
      "end_offset" : 3,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "センター",
      "start_offset" : 3,
      "end_offset" : 7,
      "type" : "word",
      "position" : 2
    }
  ]
}

"消費"、"者"、"センター"で分けられている。
この3単語が検索のキーワードになることが分かったので、 ”カロリーを消費する”なら”消費"で転置インデックスされていることが推定できるし、 ”消費する者はコンシューマー。中央はセンターという。”であれば、”消費”, ”者”, ”センター”で転置インデックスされていることが推定できると思われる。

matchによる検索を試す

結果は”消費者センター”と一致した"私は消費者センターに連絡する"の他、検索にかけた単語すべて(”消費”, ”者”, “センター“)を満たす"消費する者はコンシューマー。中央はセンターという。"

もヒットする。さらに、”者”, ”センター” は一致しないが、”消費”のみ一致した"カロリーを消費する"

もヒットする事がわかる。

これらからmatchはor検索を実行していると思われる。

GET sample1/_search
{
  "query":{
    "match":{
      "content":"消費者センター"
    }
  }
}

/////////////////////////////// 結果 //////////////////////////////////////

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 0.8630463,
    "hits" : [
      {
        "_index" : "sample1",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 0.8630463,
        "_source" : {
          "content" : "消費する者はコンシューマー。中央はセンターという。"
        }
      },
      {
        "_index" : "sample1",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.8630463,
        "_source" : {
          "content" : "私は消費者センターに連絡する"
        }
      },
      {
        "_index" : "sample1",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.2876821,
        "_source" : {
          "content" : "カロリーを消費する"
        }
      }
    ]
  }
}

match_phraseによる検索を試す

結果は"私は消費者センターに連絡する"のみヒットした。 "消費する者はコンシューマー。中央はセンターという。"といった検索時に使われる単語が全て含まれた文章は排除されているのに注目したい。これを使えば、検索時に使用したキーワードがまるまる入った文章のドキュメントだけを拾ってこれるのでは?と思う。 https://www.elastic.co/guide/en/elasticsearch/reference/7.x/query-dsl-match-query-phrase.html#query-dsl-match-query-phrase

Full text queries | Elasticsearch Reference [7.x] | Elastic

GET sample1/_search
{
  "query":{
    "match_phrase":{
      "content":"消費者センター"
    }
  }
}

///////////////////////////// 結果 ///////////////////////////////////////

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.8630463,
    "hits" : [
      {
        "_index" : "sample1",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.8630463,
        "_source" : {
          "content" : "私は消費者センターに連絡する"
        }
      }
    ]
  }
}