从零开始搭建搜索推荐系统(五十三)QUERY从分词检索进阶

聊的不止技术。跟着小帅写代码,还原和技术大牛一对一真实对话,剖析真实项目筑成的一砖一瓦,了解最新最及时的资讯信息,还可以学到日常撩妹小技巧哦,让我们开始探索主人公小帅的职场生涯吧!

(PS:本系列文章以幽默风趣风格为主,较真侠和杠精请绕道~)



一、美女的搜索条件

(上文提到,小帅看了行服小姐姐输入的搜索条件后,瞬间变成愁眉苦脸…)

小帅:“老胡,她这样搜,把我整不会了!果然,Input is evil.”
在这里插入图片描述

江华:“你搞笑吧,这不是很正常么,你在百度谷歌上不也是这样搜吗?”

小帅:“话是这样说,她不是要模糊搜索么,这样搜索根本匹配不到任何数据啊!她不加空格可能还能搜到一些商品。”

老胡:“有时候客户提的诉求并不严格是字面的意思,毕竟大家的理解层面不一样,行服说的模糊搜索,应该指的是带着她输入的字样的商品都能搜索到,所以你需要换一种实现方式。”

小帅:“那要怎样实现呢?老胡给点思路我参考下。”

老胡:“其实简单点可以尝试用分词检索,这里可以分成两部分。其一是建立倒排索引时,把需要检索的物料文本字段做好分词切片。其二是把搜索的关键词文本做分词切片,利用ElasticSearch提供的特性将两者做分词匹配,这样就能返回你当前需要检索的商品了。”

二、正排索引和倒排索引

我们知道ElasticSearch支持快速全文检索是因为它使用一种成为倒排索引的结构,那什么是倒排索引呢?我们先来重温一下正排索引和倒排索引的概念。

正排索引:指的是将文档按照顺序进行存储,每个文档包含了所有的字段信息,包括字段的值和位置,这样查询速度较快,但是占用的存储空间较大。简单来说就是-用主键ID来指向数据内容

倒排索引:则是将文档中的每个字段中的每个单词进行索引,每个单词都有一个指向包含该单词的文档的指针,这样查询速度较快,而且占用的存储空间较小。简单来说就是-用数据内容关键词来指向主键ID
在这里插入图片描述

三、分词和分词器

有了这些概念,我们能大概理解为什么ES能支持快速全文检索了,它的核心是关键词的提取。那在ES是怎样提取数据关键词的呢?这里涉及到一个重要的概念分词和分词器。

分词:是将文本按照一定的规则进行切分,得到一系列的词语。这些词语可以用来进行索引和搜索。
分词器:是一个插件,可以根据不同的需求选择不同的分词器,如英文分词器、中文分词器等。

中文的分词与英文的分词不同,因为中文没有明显的分隔符,所以需要根据词语的语法和语义进行切分。中文分词器可以使用一些现成的开源库,如IKAnalyzer、SmartChineseAnalyzer、jieba等。这些分词器可以进行中文分词,并且可以处理一些特殊情况,如人名、地名等。

这里,建立物料索引的时候我们可以使用分词器ik_max_word,使文本切割得比较细粒度且完整,query检索时候使用分词器ik_smart,减少分词数量尽量提高检索相关性。


## 测试分词器
GET _analyze
{
  "analyzer": "ik_max_word",
  "text":"1078823925183295617 测试用例店铺 8757783 8757784 aaazunTEST1"
}
GET _analyze
{
  "analyzer": "ik_smart",
  "text":"aaazunTEST1"
}

小帅:“我明白了,我这就去改一下。”

四、分词检索

(于是,小帅噼里啪啦一顿乱敲,利用reindex做数据迁移,利用elasticsearch分词能力,搜索系统2.1 elasticsearch分词版本出来了)

主要技能点

1、建立新索引skus_v2,主要用来更换mapping,使用分词器重建索引。PS:这里设置refresh时间为30s目的是加速迁移,大索引怎样迁移可以留言咨询,这里不一一展开。

PUT skus_v2
{
  "settings": {
    "refresh_interval": "30s",
    "number_of_replicas": 1,
    "number_of_shards": 5
  },
  "mappings": {
    "_doc": {
      "dynamic": "false",
      "_all": {
        "enabled": false
      },
      "dynamic_templates": [],
      "properties": {
        "skuNameChinese": {  ## 篇幅有限,其它略写如productSkuId,productSpuId均为keyword类型
          "type": "text",
          "fields": {
            "raw": {
              "type": "keyword"
            }
          },
          "analyzer": "ik_max_word",
          "search_analyzer": "ik_smart"
        }
      }
    }
  }
}

2、利用elasticsearch的reindex功能,从旧索引skus_v1迁移数据到新索引skus_v2。

## size 表示每批次迁移多少条数据
## query 表示只迁移有效的数据
## "conflicts": "proceed" 表示不中断冲突
## "op_type": "create" 表示只向目标索引插入新数据
## external表示保留最新的 version 对应的数据
## slices 表示多少个分片并行迁移
## wait_for_completion=false表示异步,防止超时
POST _reindex?wait_for_completion=false&slices=5
{
  "source": {
    "index": "skus_v1",
    "size": 10000,
    "query": {
      "bool": {
        "must": [
          {
            "term": {
              "delFlag": {
                "value": 0,
                "boost": 1
              }
            }
          }
        ]
      }
    }
  },
  "dest": {
    "index": "skus_v2",
    "version_type": "external"
  },
  "conflicts": "proceed"
}

3、利用elasticsearch的别名alias功能,指向新索引skus_v2,做在线替换。

POST /_aliases
{
  "actions": [
    {
      "remove": {
        "index": "skus_v1",
        "alias": "skus"
      }
    },
    {
      "add": {
        "index": "skus_v2",
        "alias": "skus"
      }
    }
  ]
}

4、例如搜索水杯的语句可以改写为这样。

GET skus/_search
{
  "from": 0,
  "size": 10,
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "delFlag": {
              "value": 0,
              "boost": 1
            }
          }
        },
        {
          "match": {
            "searchTag": {
              "query": "水杯",
              "operator": "AND",
              "prefix_length": 0,
              "max_expansions": 50,
              "fuzzy_transpositions": true,
              "lenient": false,
              "zero_terms_query": "NONE",
              "auto_generate_synonyms_phrase_query": true,
              "boost": 1
            }
          }
        }
      ],
      "adjust_pure_negative": true,
      "boost": 1
    }
  },
  "_source": false,
  "sort": [
    {
      "id": {
        "order": "desc"
      }
    }
  ],
  "collapse": {
    "field": "productSpuId",
    "inner_hits": {
      "name": "productSpuId",
      "ignore_unmapped": true,
      "from": 0,
      "size": 0,
      "version": false,
      "seq_no_primary_term": false,
      "explain": false,
      "track_scores": false
    }
  }
}

未完待续…

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值