商品排序不准确.md 5.1 KB

1.索引结构 2.分词的结果 3.分词配置 4.匹配规则 5.处理方案

索引的商品名称字段结构

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

分析器:

analyzer: 插入文档时,将text类型的字段做分词然后插入倒排索引

search_analyzer: 在查询时,先对要查询的text类型的输入做分词,再去倒排索引搜索

分词模式:

ik_max_word: 会将文本做最细粒度的拆分,比如会将“中华人民共和国人民大会堂”拆分为“中华人民共和国、中华人民、中华、华人、人民共和国、人民、共和国、大会堂、大会、会堂等词语。

ik_smart: 会做最粗粒度的拆分,比如会将“中华人民共和国人民大会堂”拆分为中华人民共和国、人民大会堂。

插入文档(analyzer)时用ik_max_word,在查询(search_analyzer)时用ik_smart

即:索引时最大化的将文章内容分词,搜索时更精确的搜索到想要的结果。

自定义词库

分词的时候针对一些特殊的词语在分词的时候也需要能够识别,公司产品的名称或者网络上新流行的词语 假设我们公司开发了一款新产品,命名为:数据大脑,我们希望ES在分词的时候能够把这个产品名称直接识别成一个词语。 现在使用ik分词器测试一下分词效果:

GET _analyze
{
  "analyzer":"ik_smart",
  "text":"数据大脑"
  
}

分词结果

{
  "tokens" : [
    {
      "token" : "数据",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "大脑",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 1
    }
  ]
}

根据上面的分词结果,查询时输入数据大脑,会先分词为数据大脑,然后再去文档中进行分词匹配

如果我们不用完整的词语,换成单个字,或者分词中没有分到的词语来进行查询,比如据大, 就会匹配不到商品了

这也是es分词查询和mysql模糊查询的不同

想要es中输入据大时也要匹配到名称为数据大脑的商品,就要用到自定义词库了

在自定义词库文件中配置上据大,然后再重启es重新测试一下分词效果:

GET _analyze
{
  "analyzer":"ik_smart",
  "text":"数据大脑"
  
}

分词结果

{
  "tokens" : [
    {
      "token" : "数据",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "数",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "CN_WORD",
      "position" : 1
    },
    {
      "token" : "据大",
      "start_offset" : 1,
      "end_offset" : 3,
      "type" : "CN_WORD",
      "position" : 2
    },
    {
      "token" : "据",
      "start_offset" : 1,
      "end_offset" : 2,
      "type" : "CN_WORD",
      "position" : 3
    },
    {
      "token" : "大脑",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 4
    }
  ]
}

从分词结果中可以看到,自定义词库文件中配置的据大都进行了分词,没有配置到自定义分词文件中,分词后还是已词组的方式存在

因此为了扩大查询范围,部署模板中的es有设置自定义词库,词库中包含了每个汉字又会出现其他问题,一个是分词结果会很多,另一个是分词太多会导致排序不准确(看下面的排序)

所以建议平台要维护自己分词词库,模板中配置的自定义词库更多是为了扩大搜索范围,无法保证排序是否精确

搜索排序

搜索的相关性以及算分机制 什么是相关性算分?

  • 相关性算分描述了一个文档和查询语句的匹配程度,ES 会对查询到的每个文档进行打分,打分的本质就是排序
  • ES5 之前默认的相关性打分采用 TF-IDF 算法,TF-IDF 是信息检索领域最重要的发明,现代搜索引擎都对 TF-IDF 做了大量细微的优化
  • ES6 之后开始采用 BM25 算法(对 TF-IDF 的改进),当 TF 无限增加时, BM 25 算法会使之趋于一个稳定的数值
  • 在 ES 中查询加上 explain=true 可以查看当前查询是如何打分的
  • 影响相关性算分的几个因子:
  • 词频-TF(Term Frequency):检索词在一篇文档中出现的频率,频率越高,权重越大
  1. 文档频率-DF(Document Frequency)- 检索词出现的文档数量占总文档数量的比重,DF 越大,出现的文档数越多,说明对应用意义越小,该词的相关性也就越小, 比如 "and", "is" 这些词出现非常频繁,用户反而不关心

  2. 逆向文档频率-IDF(Inverse document frequency)- 因为 DF 的值算出来结果范围会非常大,为了减少 DF 对打分的影响,引入了 IDF,其实就是对 DF 取对数来减少打分影响

  3. 字段长度(Field-length)- 搜索的字段越短,相关性越高