ES分词导致查询结果不准确

问题现象

索引里面有数据,而没有查询出来。

如下图所示,术语库(索引)中里面有一条数据的原文是“层”,而根据完整的原文来查询该原文中的术语,并未将该术语查询出来。

根据原文查询该原文中的术语,并未查询到上面的术语:

原因分析

这是由于es分词器导致的。由于es在执行查询时,会先将原文进行分词,再将分词后的结果拿去匹配。

查看分词结果:

由于待查询的字段采用的分词器是optimizeIK,所以这里使用该分词器查询原文分词后的结果

分词结果:

由于分词结果并没有“层”这条数据,所以也不会匹配出“层”这条术语。

解决方案

两种解决方案,分别是增加自定义词库和查询前分词

增加自定义词库

也就是自定义一个词库,让es遇到自定义词库中的词时也进行分词。比如将上述的“层”加入自定义词库当中,如何es分词时则会将“层”给分词出来。这需要改动es的配置文件IKAnalyzer.cfg.xml,修改文件里面的扩展配置指向自定义词库。

这种方案的缺点是不能一次性解决该问题,因为需要遇到此问题时,才能将未查询到的词组加入自定义词库,而且需要重启es,会影响线上功能。

查询前分词

所谓查询前分词,也就是不直接使用原文进行查询,而是先将原文通过多个分词器进行分词,再使用分词后的结果进行查询。比如将原文分别进行standard分词器分词和optimizeIK分词器分词,将两种分词器的分词结果进行合并,然后再进行查询。

先分词:

使用分词后的结果进行匹配:

es命令:

GET /tb/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "terms": {
            "dbId": [
              "19841159f25845008fad2512aa91f48b"
            ]
          }
        }
      ],
      "should": [
        {
          "match_phrase": {
            "original": "侏"
          }
        },
        {
          "match_phrase": {
            "original": "罗"
          }
        }
        ....
      ],
      "minimum_should_match": 1, 
      "filter": [
        {
          "script": {
            "script": {
              "lang": "painless",
              "source": "String str = params.val;String strLower = params.valLower;String val = doc['original.keyword'].value;return str.contains(val) || strLower.contains(val.toLowerCase());",
              "params": {
                "val": "侏罗层系主力区块年注采比变化",
                "valLower": "侏罗层系主力区块年注采比变化"
              }
            }
          }
        }
      ]
    }
  }
}

缺点是如果分词结果太多,会比较消耗性能

目前是采用第二种方案来解决该问题的。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值