一、问题描述

用一句话总结问题便是:使用ik分词器,“长”关键字wildcard搜索不到数据

POST /lpm-company-dev/_search
{
  "query":{
    "bool" : {
      "must" : [
        {
          "bool" : {
            "should" : [
              {
                "wildcard" : {
                  "name" : {
                    "wildcard" : "*鸿运*",
                    "boost" : 1.0
                  }
                }
              }
            ],
            "adjust_pure_negative" : true,
            "boost" : 1.0
          }
        }
      ],
      "adjust_pure_negative" : true,
      "boost" : 1.0
    }
  }
}

关键词为“鸿运”可以搜索到数据,但是“鸿运物流”却搜索不到。

二、问题分析

mapping分词器设置

"name": {
  "type": "text",
  "analyzer": "ik_max_word",
  "search_analyzer": "ik_smart"
}

分析

ik_max_word解析结果:

POST /lpm-company-dev/_analyze
{
  "text": [
    "阜阳市鸿运物流有限公司"
  ],
  "analyzer": "ik_max_word"
}

分析结果:

{
  "tokens" : [
    {
      "token" : "阜阳市",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "阜阳",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "CN_WORD",
      "position" : 1
    },
    {
      "token" : "市",
      "start_offset" : 2,
      "end_offset" : 3,
      "type" : "CN_CHAR",
      "position" : 2
    },
    {
      "token" : "鸿运",
      "start_offset" : 3,
      "end_offset" : 5,
      "type" : "CN_WORD",
      "position" : 3
    },
    {
      "token" : "物流",
      "start_offset" : 5,
      "end_offset" : 7,
      "type" : "CN_WORD",
      "position" : 4
    },
    {
      "token" : "有限公司",
      "start_offset" : 7,
      "end_offset" : 11,
      "type" : "CN_WORD",
      "position" : 5
    },
    {
      "token" : "有限",
      "start_offset" : 7,
      "end_offset" : 9,
      "type" : "CN_WORD",
      "position" : 6
    },
    {
      "token" : "公司",
      "start_offset" : 9,
      "end_offset" : 11,
      "type" : "CN_WORD",
      "position" : 7
    }
  ]
}

ik_smart解析结果:

POST /lpm-company-dev/_analyze
{
  "text": [
    "阜阳市鸿运物流有限公司"
  ],
  "analyzer": "ik_smart"
}
{
  "tokens" : [
    {
      "token" : "阜阳市",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "鸿运",
      "start_offset" : 3,
      "end_offset" : 5,
      "type" : "CN_WORD",
      "position" : 1
    },
    {
      "token" : "物流",
      "start_offset" : 5,
      "end_offset" : 7,
      "type" : "CN_WORD",
      "position" : 2
    },
    {
      "token" : "有限公司",
      "start_offset" : 7,
      "end_offset" : 11,
      "type" : "CN_WORD",
      "position" : 3
    }
  ]
}

三、猜想

ik分词之后,wildcard就不能正常使用了?目前经过测试,答案正是如此;我们又没有太多的精力来维护ik分词器的词典。

修改属性配置

于是重建索引,不再使用ik分词器,关键字段设置为:

    "name": {
          "type": "text",
          "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
    }

使用ik分词器时,是看不到name.keyword属性的;默认分词器才会有。

重建索引后测试,wildcard可以正常使用了。

POST /lpm-company-dev/_search
{
  "query":{
    "bool" : {
      "must" : [
        {
          "bool" : {
            "should" : [
              {
                "wildcard" : {
                  "name.keyword": {
                    "wildcard" : "*鸿运物流*",
                    "boost" : 1.0
                  }
                }
              }
            ],
            "adjust_pure_negative" : true,
            "boost" : 1.0
          }
        }
      ],
      "adjust_pure_negative" : true,
      "boost" : 1.0
    }
  }
}

四、总结

本总结以搜索name属性为例。

  1. 搜索字段为中文时,使用ik分词器会影响wildcard搜索,搜索属性为“name”,且无name.keyword属性。
  2. 搜索字段为中文时,使用默认分词器时wildcard可以正常搜索,搜索属性应为name.keyword
  3. 搜索字段为数字或英文构成的字符串时,搜索属性可以使用namename.keyword

遗留问题

上述最终解决方法是没有再使用ik分词器匹配,如有朋友们有更好的方案,欢迎留下您的脚印👣👣~
主要纠结的点在于:
1、不想自己维护词典,ik分词器的字典更新后需要es重启;
2、ik分词和wildcard查询的相互影响怎么避免?

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐