ES的match_phrase_prefix语句查询结果不精准

问题

在工作中使用match_phrase_prefix语句进行搜索时,明明有满足条件的文档,但是却没有查询出来。具体操作步骤如下。

查询语句:

POST /tmproj/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match_phrase_prefix": {
            "original": {
              "query": "A Survey on Auto"
            }
          }
        }
      ]
    }
  }
}

查询结果里面没有查询出目标文档:

调整查询语句,增加搜索条件中最后一个单词的长度:

POST /tmproj/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match_phrase_prefix": {
            "original": {
              "query": "A Survey on Autom"
            }
          }
        }
      ]
    }
  }
}

查询出了目标文档:

与上一个查询条件相比,只是把搜索文本的最后一个单词由"Auto"变成了"Autom"

原因

第一反应是自己对match_phrase_prefix语句的使用方式产生了误解。

官网介绍

随即查看es官网:match_phrase_prefix官网介绍

发现一开始就有介绍:

即:返回包含所提供文本中指定词汇的文档,其排列顺序与所提供的顺序一致。所提供的文本中的最后一个词被视为前缀,用于匹配以该词开头的任何词汇。

备注

感觉自己没有理解错误,但是继续往下看发现了问题所在:

即:

虽然使用“match_phrase_prefix”查询进行搜索自动补全操作起来比较简便,但有时可能会产生令人困惑的结果。
例如,考虑查询字符串“quick brown f”。该查询的工作原理是将“quick”和“brown”组合成一个短语查询(即“quick”必须存在,并且必须紧接“brown”之后)。然后,它会查看已排序的词典,找出以“f”开头的前 50 个词,并将这些词添加到短语查询中。
问题在于前 50 个字符中可能不包含“fox”这个单词,所以“quick brown fox”这个短语是找不到的。但这种情况通常不会成为问题,因为用户会继续输入更多的字母,直到他们要查找的单词出现为止。

重要内容解释

重点分析一下这段话:

Then it looks at the sorted term dictionary to find the first 50 terms that begin with f, and adds these terms to the phrase query.

looks at the sorted term dictionary

排序后的词条词典里查找

什么是 sorted term dictionary

它来自哪里?

这是 Lucene 底层索引结构,也就是:

ES 在建立索引时,对所有分词做过:

分词 → 去重 → 字典序排序 → 生成的词典表 

例子:你的文档里有这些词:

fox
fan
food
face
family
fruit
...

ES 会把它们排序后变成:

face
family
fan
food
fox
fruit
...

这张排好序的单词表,就是

sorted term dictionary

它存在于磁盘的 Lucene 索引文件中。


to find the first 50 terms that begin with f

找到字典序里【最前面的 50 个】以 f 开头的词

重点:

不是找所有匹配的!

而是只取前 50 个!

默认 max_expansions = 50


and adds these terms to the phrase query

翻译:

把这 50 个词,加入到短语查询中

也就是说:

quick brown + [fan / face / food / ... 50个词]

ES 只会去匹配:

quick brown fan
quick brown face
quick brown food
...

它不会去匹配其它词!


最关键一句:

The problem is that the first 50 terms may not include the term fox

翻译:

问题在于:前 50 个词里,可能不包含 fox!

例子:

排序后的词典:

1. face
2. family
3. fan
4. far
5. fat
6. favor
...
50. fly
51. fox

fox 排在第 51 位以后!

就会出现明明存在,但查不到!

解决

从官网介绍也可以看出,解决办法有两种

增大max_expansions参数的值

调整max_expansions参数后(经过试验,我的案例需要调整到94),可以查询到目标文档。

POST /tmproj/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match_phrase_prefix": {
            "original": {
              "query": "A Survey on Auto",
              "max_expansions": 94
            }
          }
        }
      ]
    }
  }
}

多输入搜索文本字母

即不断增加查询文本的长度,我的案例是将最后一个单词由"Auto"调整为"Autom"后即可查询出目标文档。

POST /tmproj/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match_phrase_prefix": {
            "original": {
              "query": "A Survey on Autom"
            }
          }
        }
      ]
    }
  }
}

总结

match_phrase_prefix 工作原理:

  1. 前面所有词 = 短语精确匹配

  2. 最后一个词 = 去词典查前缀

  3. 只取前 50 个(max_expansions=50)

  4. 把这 50 个词拼回短语查询

  5. 如果你的词不在这 50 个里 → 查不到!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值