由 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

相关文章

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

好题——hdu2522(小数问题:求1/n的第一个循环节)

好喜欢这题,第一次做小数问题,一开始真心没思路,然后参考了网上的一些资料。 知识点***********************************无限不循环小数即无理数,不能写作两整数之比*****************************(一开始没想到,小学没学好) 此题1/n肯定是一个有限循环小数,了解这些后就能做此题了。 按照除法的机制,用一个函数表示出来就可以了,代码如下

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

购买磨轮平衡机时应该注意什么问题和技巧

在购买磨轮平衡机时,您应该注意以下几个关键点: 平衡精度 平衡精度是衡量平衡机性能的核心指标,直接影响到不平衡量的检测与校准的准确性,从而决定磨轮的振动和噪声水平。高精度的平衡机能显著减少振动和噪声,提高磨削加工的精度。 转速范围 宽广的转速范围意味着平衡机能够处理更多种类的磨轮,适应不同的工作条件和规格要求。 振动监测能力 振动监测能力是评估平衡机性能的重要因素。通过传感器实时监

缓存雪崩问题

缓存雪崩是缓存中大量key失效后当高并发到来时导致大量请求到数据库,瞬间耗尽数据库资源,导致数据库无法使用。 解决方案: 1、使用锁进行控制 2、对同一类型信息的key设置不同的过期时间 3、缓存预热 1. 什么是缓存雪崩 缓存雪崩是指在短时间内,大量缓存数据同时失效,导致所有请求直接涌向数据库,瞬间增加数据库的负载压力,可能导致数据库性能下降甚至崩溃。这种情况往往发生在缓存中大量 k

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

【VUE】跨域问题的概念,以及解决方法。

目录 1.跨域概念 2.解决方法 2.1 配置网络请求代理 2.2 使用@CrossOrigin 注解 2.3 通过配置文件实现跨域 2.4 添加 CorsWebFilter 来解决跨域问题 1.跨域概念 跨域问题是由于浏览器实施了同源策略,该策略要求请求的域名、协议和端口必须与提供资源的服务相同。如果不相同,则需要服务器显式地允许这种跨域请求。一般在springbo

题目1254:N皇后问题

题目1254:N皇后问题 时间限制:1 秒 内存限制:128 兆 特殊判题:否 题目描述: N皇后问题,即在N*N的方格棋盘内放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在同一斜线上。因为皇后可以直走,横走和斜走如下图)。 你的任务是,对于给定的N,求出有多少种合法的放置方法。输出N皇后问题所有不同的摆放情况个数。 输入

vscode中文乱码问题,注释,终端,调试乱码一劳永逸版

忘记咋回事突然出现了乱码问题,很多方法都试了,注释乱码解决了,终端又乱码,调试窗口也乱码,最后经过本人不懈努力,终于全部解决了,现在分享给大家我的方法。 乱码的原因是各个地方用的编码格式不统一,所以把他们设成统一的utf8. 1.电脑的编码格式 开始-设置-时间和语言-语言和区域 管理语言设置-更改系统区域设置-勾选Bata版:使用utf8-确定-然后按指示重启 2.vscode