由 Elasticsearch 空间换时间的线上问题说开去......

2023-10-08 07:50

本文主要是介绍由 Elasticsearch 空间换时间的线上问题说开去......,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、线上实战问题

请教一下各位朋友,关于 ngram 的 slop 影响搜索结果?

1、前置条件:

  • 商品A的SPUCodeText为:OWBB050C99JER0021001

  • 商品B的SPUCodeText为:VSA00293ABBLACKFW2022

  • 商品C的SPUCodeText为:2WHGG0VNT03HHFC99FW2022

2、现况:搜索商品A的SPUCodeText编码:OWBB050,slop设置为49-54无法查询出该商品;slop设置为55及其以上的值,才可以查询出商品A;

3、追求目标:搜索SPUCodeText任意一组4个数字及其以上的组合,即可查询出该商品?

篇幅原因,省去了 DSL 定义和查询语句。

——题目来源:死磕Elasticsearch 知识星球https://t.zsxq.com/08rmVBnhA

2、问题释义

大前提:商品码的存储类似之前咱们视频讲过的手机号的存储,传统的分词器(默认的 standard、中文的 ik_max_word 等)都无法搞定。

需要借助于 Ngram 自定义分词实现。

那么问题来了:Ngram 分词后的数据,用 match_phrase + slop 检索出现了问题,必须 slop 设置很大才可以搞定!

什么原因导致的呢?有没有更为简洁的方法?

3、Elasticsearch 空间换时间

啥叫空间换时间,拿当下世界杯的例子一看就明白。

如下解说员说的:“15人才能打赢”。15人比正常的11人远多4人,这就是多了空间,而换取了时间或结果。当然,比赛事实远非解说员所说。

667a4e1381560c16f6d1ae2ac2d47c65.png

Elasticsearch 中 Ngram 分词本质就是空间换时间的方式,以极小的粒度切分文档,空间存储激增、写入速度会受到影响,但换来了检索效率的提升!

4、精简问题后的实现

PUT /products-001
{"settings": {"max_ngram_diff": 40,"analysis": {"analyzer": {"ruishan_ngram_analyzer": {"filter": ["lowercase"],"type": "custom","tokenizer": "ruishan_ngram_tokenizer"}},"tokenizer": {"ruishan_ngram_tokenizer": {"token_chars": ["letter","digit"],"min_gram": 3,"type": "ngram","max_gram": 40}}}},"mappings": {"properties" : {"id" : {"type" : "keyword"},"sPUCodeText" : {"type" : "text","analyzer" : "ruishan_ngram_analyzer"}}}
}PUT products-001/_bulk
{"index":{"_id":1}}
{"id":1,"sPUCodeText":"OWBB050C99JER0021001"}
{"index":{"_id":2}}
{"id":2,"sPUCodeText":"VSA00293ABBLACKFW2022"}
{"index":{"_id":3}}
{"id":3,"sPUCodeText":"2WHGG0VNT03HHFC99FW2022"}GET products-001/_search
{"query": {"bool": {"must": [{"match": {"sPUCodeText": {"query": "OWBB050"}}}]}}
}

看如下结果,一个 match 就可以搞定了!

e77fa103563fd97edd7926f38b720276.png

再来,match_phrase 可以不?

4baec711ab61ada4dc679f88e3ed90d1.png

那么match_phrase 加上较大的 slop 呢?能搞定吗?!

经反复测验,需要slop 至少设置 52 才可以搞定,如下所示。

6c2707add5deaa1586c69e7db1450057.png

为什么呢?为什么是 52 呢?

5、match_phrase 短语匹配检索的本质?

通俗点说:query 部分待检索语句(如开篇:OWBB050)的分词结果要和文档(如:OWBB050C99JER0021001)中的分词结果顺序和位次完全一致才可以!

可以通过 analyzer api 查看分词结果,如下所示:

POST products-001/_analyze
{"field": "sPUCodeText","text": ["OWBB050C99JER0021001"]
}
50d00521d6629f3901e4904918bf2b3f.png

分词后的词项单元,“OWBB050”如下图左侧所示,“OWBB050C99JER0021001”如下图右侧所示。

bf9477c522f95fdff3d417421c4140bf.png

两者并不一致,这是导致无法匹配的原因,也就是有偏差!

6、match_phrase 短语检索下参数 slop 本质

一个图彻底搞明白!

ac7dc114a62b201856e11b6b4f9053f9.png

相同颜色代表:待检索词和源文档中分词结果一样的词项。

最大差值的计算方法,比如:分词后的词项“050”,在待检索词中位次为 15, 在源文档“OWBB050C99JER0021001”为67。

差了:67-15=52。

所以,slop 补齐这个最大的差值 52,就可以实现检索和数据的召回!

slop 设置为 51,就不可以!至少 52 或者52以上才可以召回数据。

217e160935d1339fbc41c8c21f0d3bee.png

7、小结

类似 Ngram 分词后,我们已经在空间层面下足了功夫!就没必要时间层面、检索层面下功夫了!

直接 match 检索必然能检索到结果!

08f0e0b5dd827833187b5e487f57e433.png

如上的写法 filter 是可以走缓存的,推荐使用。

那,有没有更快的写法呢?

f66bbd27ea3a47108d8c57826a286874.png

仔细的同学会发现,“OWBB05”都变成小写“owbb05”才可以召回数据,而直接大写直接 term 检索无法召回数据!

为什么呢?留给大家留言思考!

4253633d582fae0ea56e39e7fb9582fe.png

推荐阅读

  1. 全网首发!从 0 到 1 Elasticsearch 8.X 通关视频

  2. 重磅 | 死磕 Elasticsearch 8.X 方法论认知清单(2022年国庆更新版)

  3. 如何系统的学习 Elasticsearch ?

c7bf34ae9530cabe384d68d9dfb6406e.jpeg

更短时间更快习得更多干货!

和全球 1800+ Elastic 爱好者一起精进!

f3d638d8ca2c8d40e9edac956013ab25.gif

比同事抢先一步学习进阶干货!

这篇关于由 Elasticsearch 空间换时间的线上问题说开去......的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/163812

相关文章

IDEA和GIT关于文件中LF和CRLF问题及解决

《IDEA和GIT关于文件中LF和CRLF问题及解决》文章总结:因IDEA默认使用CRLF换行符导致Shell脚本在Linux运行报错,需在编辑器和Git中统一为LF,通过调整Git的core.aut... 目录问题描述问题思考解决过程总结问题描述项目软件安装shell脚本上git仓库管理,但拉取后,上l

idea npm install很慢问题及解决(nodejs)

《ideanpminstall很慢问题及解决(nodejs)》npm安装速度慢可通过配置国内镜像源(如淘宝)、清理缓存及切换工具解决,建议设置全局镜像(npmconfigsetregistryht... 目录idea npm install很慢(nodejs)配置国内镜像源清理缓存总结idea npm in

pycharm跑python项目易出错的问题总结

《pycharm跑python项目易出错的问题总结》:本文主要介绍pycharm跑python项目易出错问题的相关资料,当你在PyCharm中运行Python程序时遇到报错,可以按照以下步骤进行排... 1. 一定不要在pycharm终端里面创建环境安装别人的项目子模块等,有可能出现的问题就是你不报错都安装

idea突然报错Malformed \uxxxx encoding问题及解决

《idea突然报错Malformeduxxxxencoding问题及解决》Maven项目在切换Git分支时报错,提示project元素为描述符根元素,解决方法:删除Maven仓库中的resolv... 目www.chinasem.cn录问题解决方式总结问题idea 上的 maven China编程项目突然报错,是

Python爬虫HTTPS使用requests,httpx,aiohttp实战中的证书异步等问题

《Python爬虫HTTPS使用requests,httpx,aiohttp实战中的证书异步等问题》在爬虫工程里,“HTTPS”是绕不开的话题,HTTPS为传输加密提供保护,同时也给爬虫带来证书校验、... 目录一、核心问题与优先级检查(先问三件事)二、基础示例:requests 与证书处理三、高并发选型:

前端导出Excel文件出现乱码或文件损坏问题的解决办法

《前端导出Excel文件出现乱码或文件损坏问题的解决办法》在现代网页应用程序中,前端有时需要与后端进行数据交互,包括下载文件,:本文主要介绍前端导出Excel文件出现乱码或文件损坏问题的解决办法,... 目录1. 检查后端返回的数据格式2. 前端正确处理二进制数据方案 1:直接下载(推荐)方案 2:手动构造

Python绘制TSP、VRP问题求解结果图全过程

《Python绘制TSP、VRP问题求解结果图全过程》本文介绍用Python绘制TSP和VRP问题的静态与动态结果图,静态图展示路径,动态图通过matplotlib.animation模块实现动画效果... 目录一、静态图二、动态图总结【代码】python绘制TSP、VRP问题求解结果图(包含静态图与动态图

MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决

《MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决》MyBatis默认开启一级缓存,同一事务中循环调用查询方法时会重复使用缓存数据,导致获取的序列主键值均为1,... 目录问题原因解决办法如果是存储过程总结问题myBATis有如下代码获取序列作为主键IdMappe

java时区时间转为UTC的代码示例和详细解释

《java时区时间转为UTC的代码示例和详细解释》作为一名经验丰富的开发者,我经常被问到如何将Java中的时间转换为UTC时间,:本文主要介绍java时区时间转为UTC的代码示例和详细解释,文中通... 目录前言步骤一:导入必要的Java包步骤二:获取指定时区的时间步骤三:将指定时区的时间转换为UTC时间步

MySQL8.0临时表空间的使用及解读

《MySQL8.0临时表空间的使用及解读》MySQL8.0+引入会话级(temp_N.ibt)和全局(ibtmp1)InnoDB临时表空间,用于存储临时数据及事务日志,自动创建与回收,重启释放,管理高... 目录一、核心概念:为什么需要“临时表空间”?二、InnoDB 临时表空间的两种类型1. 会话级临时表