Elasticsearch 警惕使用 wildcard 检索!然后呢?

article/2025/9/17 1:36:29

1、wildcard 检索定义

wildcard 检索可以定义为:支持通配符的模糊检索。

类似 Mysql 中的 like 模糊匹配,如下所示:

Elasticsearch 中的 wildcard 使用方式如下:

通配符运算符是匹配一个或多个字符的占位符。

通配符支持两种:

  • ? : 支持模糊匹配单个字符。举例:Ma?s 仅能匹配:Mars, Mass, 和 Maps。

  • : 支持模糊匹配零个或者多个字符。举例:Ma*s 能匹配:Mars, Matches 和 Massachusetts等。

2、全局视野——wildcard 检索所处位置

全局认知非常重要,检索核心类型大致(非严谨、精确)分为:精准匹配检索(Term-level queries)和基于分词的全文匹配检索(Full text queries)。

全文匹配检索细分如下:

精准匹配检索细分如下:

也就是:wildcard 是和Term、Terms检索平级的检索。

3、wildcard 检索适用场景

适用于:召回率要求高的业务场景。

基于分词的全文检索,可能会导致明明存在,但是检索不到。可能的原因如下:

  • 原因1:基础词库不完备;

  • 原因2:分词粒度不精确。

举个例子一看就明白了:

前置说明:

  • 1、纯属举例,不涉及针对具体人。

  • 2、Ik 词典main.dic 非原生,做了互联网词库的扩展,但词库中依然没有“刘强东”三个字。

  • 3、如果你在本地测试结果和文章不一致,极大可能是词典不一样导致的。

PUT test-004
{"mappings": {"properties": {"title": {"type": "text","analyzer": "ik_max_word","fields": {"keyword": {"type": "keyword"}}}}}
}POST test-004/_bulk
{"index":{"_id":1}}
{"title":"英文官网承认刘强东一度被捕的原因是涉嫌XX"}
{"index":{"_id":2}}
{"title":"别提了朋友哥哥刘强东窗事发了"}
{"index":{"_id":3}}
{"title":"刘强东施效颦,没想到竟然收获了流量"}
{"index":{"_id":4}}
{"title":"刘强东是谁?我不认识"}POST test-004/_search
{"query": {"match_phrase": {"title": "刘强东"}}
}

用的短语检索 match_phrase,搜索结果如下:

原因说明,analyzer API 能说明一切。

POST test-004/_analyze
{"text": ["京东英文官网承认刘强东一度被捕的原因是涉嫌XX"],"analyzer": "ik_max_word"
}

分词结果如下:

面对如上召回情况,部分不追求精准率只追求召回率的业务场景,可能会需要文档_id = 1、2、3、4 全部都要召回。

这时候,如果不改变分词的情况下,可能的解决方案之一就是:wildcard 检索实现。

POST test-004/_search
{"query": {"wildcard": {"title.keyword": "*刘强东*"}}
}

如上的方式,文档1、2、3、4全部召回。

相当于在原有DSL的基础上,只改动检索方式和字段名称就搞定了产品经理的提高召回率的需求。

貌似,可以交差大吉了。实则,有非常大的隐患。

4、wildcard 可能的风险

官方文档是这么说的:

中文含义是:避免以*或?开头的模式。这会增加查找匹配项所需的迭代次数并降低搜索性能。

wildcard 到底有多慢?如下示例可见一斑:

wildcard 检索字段指定的字符数多了以后,会报错如下:

在 wood 大叔 2017年的文章中,曾经指出如下的核心点:

  • 4.1 出现问题

用户输入的字符串长度没有做限制,导致首尾通配符中间可能是很长的一个字符串。后果就是对应的wildcard Query执行非常慢,非常消耗CPU。

  • 4.2 根本原因

为了加速通配符和正则表达式的匹配速度,Lucene4.0开始会将输入的字符串模式构建成一个DFA (Deterministic Finite Automaton),带有通配符的pattern构造出来的DFA可能会很复杂,开销很大。

源码及细节推荐阅读:

https://elasticsearch.cn/article/171

https://elasticsearch.cn/article/186

5、wildcard 实战中的悲剧

如下,采用原汁原味的技术群交流内容,更具有说服力。

更能警示大家:慎用 Wildcard!

5.1 悲剧1:一味的满足产品经理的需求,wildcard 不考虑性能的乱用。

5.2 悲剧2:wildcard 参数传了一篇文章进来,导致集群宕机!

5.3 悲剧3:wildcard 搜索一百个汉字,导致CPU利用率 100%!

注意是:不同100个字组合,一直搜。

5.4 悲剧4:客户现场演示,集群宕机!

根因:bool 组合了近 100 组+ wildcard 不同关键词的检索。

6、wildcard 可能的替代方案

在寻求解决方案的时候,我们要先问一下:为什么大家喜欢用 wildcard 实现模糊检索?

得到的答复往往是:顺手,类似Mysql like 查询,短、平、快的达到了产品经理的要求,满足了项目需求。

但,这忽略了性能问题以及可能带来的灾难后果。

所以,解决方案应该从根源上入手,以寻求彻底解决。

6.1 替代方案一:写入时分词优化,使用 Ngram 分词。

更细粒度分词,更有利于数据的召回!

PUT test-005
{"settings": {"index.max_ngram_diff": 10,"analysis": {"analyzer": {"my_analyzer": {"tokenizer": "my_tokenizer"}},"tokenizer": {"my_tokenizer": {"type": "ngram","min_gram": 3,"max_gram": 10,"token_chars": ["letter","digit"]}}}},"mappings": {"properties": {"title": {"type": "text","analyzer": "my_analyzer","fields": {"keyword": {"type": "keyword"}}}}}
}POST test-005/_bulk
{"index":{"_id":1}}
{"title":"英文官网承认刘强东一度被捕的原因是涉嫌性侵"}
{"index":{"_id":2}}
{"title":"别提了朋友哥哥刘强东窗事发了"}
{"index":{"_id":3}}
{"title":"刘强东施效颦,没想到竟然收获了流量"}
{"index":{"_id":4}}
{"title":"刘强东是谁?我不认识"}POST test-005/_search
{"query": {"match_phrase": {"title": "刘强东"}}
}

Ngram 实现推荐:

Elasticsearch能检索出来,但不能正确高亮怎么办?

6.2 替代方案二:7.9 + 以上的版本,使用 wildcard 数据类型。

wildcard 类型出现的目的:一方面避免了某些场景下分词查询不准确的问题,另一方面也解决了通配符和正则检索的效率问题。

注意:新上的数据类型 wildcard,而非 wildcard 检索。

使用方法参见:

https://www.elastic.co/guide/en/elasticsearch/reference/master/keyword.html#wildcard-field-type。

6.3 禁用方案:禁止使用wildcard 模糊检索

特殊业务场景需要禁止:wildcard 检索。

实现如下:

PUT _cluster/settings
{"transient": {"search.allow_expensive_queries": false}
}

需要强调的是: 

"search.allow_expensive_queries"  是 7.7+ 版本才有的功能,早期版本会报错。

7、小结

由于技术惯性,我们习惯于相同或者相通技术的技术迁移,比如:mysql like 查询迁移到 Elasticsearch 中的 wildcard 模糊检索。但迁移的时候一定要注意:不同技术点的实现差异,同时要多关注技术点不能可能导致的性能问题。

即便 2017年 wood 大叔就发了两篇文章让大家警惕 wildcard 模糊检索可能带来的性能问题。但四年后的今天,仍然很多公司的实战业务中还未考虑性能及后果的前提下,乐此不疲的用着 wildcard 检索!

所以,本文算是 wood 大叔的 wildcard 警示文章接力,希望更多人看到。

参考:

https://t.zsxq.com/Y3zv7Eq 

https://t.zsxq.com/bm62zZf


推荐:

  1. 如何系统的学习 Elasticsearch ?

  2. 从实战中来,到实战中去——Elasticsearch 技能更快提升方法论

  3. 重磅 | 死磕 Elasticsearch 方法论认知清单(2020年国庆更新版)

  4. 探究 | 明明存在,怎么搜索不出来呢?


中国最大的 Elastic 非官方公众号

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

点击查看“阅读原文”,更短时间更快习得更多干货。和全球 1000 位+ Elastic 爱好者(含中国 50%+ Elastic 认证工程师)一起每日精进 ELK 技能!


http://chatgpt.dhexx.cn/article/cleE9HUO.shtml

相关文章

VIO你用对了吗

VIO(Virtual Input/Output)有两个主要功能 监测设计中的内部信号; 驱动设计中的内部信号。 既然是Virtual(虚拟的),就表明这个输入或输出并不是真实存在于FPGA设计中。下图显示了VIO的输入、输出管脚。其…

VIO(notes) —— (3)VIO残差构建与IMU预积分

VIO残差构建与IMU预积分 一、VIO残差函数的构建1. 系统所需的状态变量2. 视觉重投影误差2.1 视觉重投影误差2.2 逆深度参数化2.3 VIO 中基于逆深度的重投影误差 3. 预积分模型由来及意义3.1 为什么需要预积分?3.2 怎么预积分?3.3 预积分是什么&#xff1…

深蓝学院VIO课程学习笔记 VIO概述

VIO概述 1. VIO整体概述 松耦合:各部分自己算自己的,最后单独把数据来算 紧耦合:同时考虑这两个问题(效果更好) IMUGPS精度可以达到cm级,但是受环境影响比较大 融合方案 采用卡尔曼滤波,当一边…

海思3559 sample解析:vio

前言 拿到开发板,编完了平台sample,自然按捺不住要去简单学习测试了。打开最直观相对也比较简单的vio例程做个到手分析和流程梳理吧 测试 一开始自然是最磕磕绊绊的,连上HDMI线,串口登录后运行,屏幕乌漆嘛黑&#xff…

从零手写VIO(7)

从零手写VIO(7) 文章目录 从零手写VIO(7)前言一、VINS-Course代码解析二、作业(7)1.simulation-test.cpp修改2.Sysytem.cpp修改3.config文件夹下euroc_config.yaml参数修改4.param.h修改4.1无噪声4.2小噪声4.3大噪声 总结 前言 一、VINS-Course代码解析…

运行msckf_vio

1、编译 cd ~/msckf catkin_make --pkg msckf_vio --cmake-args -DCMAKE_BUILD_TYPERelease2、运行(运行euroc数据集) 首先roscore开启ros节点 cd ~/msckf source ~/msckf/devel/setup.bash roslaunch msckf_vio msckf_vio_euroc.launchcd ~/msckf sou…

深蓝学院-手写VIO作业-第二章

文章目录 一、基础作业,必做环境配置说明a. ROS环境搭建b. Matlab安装 1、设置IMU 仿真代码中的不同的参数,生成Allen 方差标定曲线。a. 对于非ROS:生成运动imu数据b.对于ROS: 专门生成静止 imu 数据,用于 allan 方差标定 2、将IM…

【代码阅读】PL-VIO

〇、写在前面 PL-VIO采用的通信是ROS,所以并不能像ORBSLAM那样按照执行顺序来理顺,因为ORBSLAM是有一个真正意义上的主函数的,经过CMakeList的编辑产生的可执行文件会有一个开始,但是PL-VIO用的是ROS,其内部通信是节点…

VIO:飞行机器人单目VIO算法测评

转:https://blog.csdn.net/u012348774/article/details/81414264 泡泡图灵智库,带你精读机器人顶级会议文章 标题:A Benchmark Comparison of Monocular Visual-Inertial Odometry Algorithms for Flying Robots 作者:Jeffrey De…

VIO学习笔记一

1. IMU(Inertial Measurement Unit,惯性测量单元) 典型6轴IMU以较高频率(≥100Hz)返回被测量物体的角速度与加速度。受自身温度、零偏、振动等因素干扰,积分得到的平移和旋转容易漂移。IMU本身由一个陀螺仪…

VIO仿真

使用turtelbot3仿真,发现gazebo的imu没有重力加速度。放弃。还是使用公开数据集。 使用这个仿真​​​​​​vio_data_simulation/src at ros_version HeYijia/vio_data_simulation GitHub 看一下如何用这个仿真跑起来vio。 -- 将特征点反投回图像,…

3.4.1 VIO虚拟以太网原理

最后更新2021/08/12 VIO Server在此完全实现了一个标准的以太网交换机的功能,现在业界都有了高大上的名称:SDN(Software Defined Network),如果没有足够的网络知识(幸好只是网络链路层)&#x…

Vivado调用VIO核

文章目录 前言一、IP核的介绍二、VIO核1.作用2.调用方法 总结 前言 提示:本篇文章所使用的软件为Vivado2018.3: 以四选一数据选择器为例,使用verilog hdl语言以及Vivado自带的VIO,IP来实现功能 提示:以下是本篇文章正文内容&…

海思3519 VIO Sample例程讲解

海思VIO Sample例程讲解 海思SDK解压出来后,Sample包含各个功能模块的历程,本篇讲解VIO Sample历程。 进入VIO模块可以看到,VIO的main函数文件,先从main函数执行程序。 进入文件后首先看下VIO实现的功能,可以看到VIO…

PL-VIO论文阅读

PL-VIO: Tightly-Coupled Monocular Visual–Inertial Odometry Using Point and Line Features Yijia He 1,2,* , Ji Zhao 3, Yue Guo 1,2, Wenhao He 1 and Kui Yuan 1 2018 摘要 To address the problem of estimating camera trajectory and to build a structural 3D m…

DM-VIO简析

今天主要是针对DMVIO/DM-VIO的简析,中文网上有的东西都太少了,只能靠看完论文和组员们一起改代码。Lukas组这个东西在中文网被称为有史以来最好的VIO,但是实际过程中我们还是发现了许多不完美的地方。。。(比如ZUPT更新改造中该有的问题仍然在…

VIOSLAM 综述

文章目录 1.VIO 松耦合/紧耦合。2. 相机和IMU的缺点及互补性3. VIO融合算法流程及其模块分解:4. VIO 算法核心:5. 实验结果与总结:6. 参考文献: 1.VIO 松耦合/紧耦合。 Visual-Inertial Odometry(VIO)即视觉惯性里程计,有时也叫视觉惯性系统…

VIO系统介绍

VIO(visual-inertial odometry)即视觉惯性里程计,有时也叫视觉惯性系统(VINS,visual-inertial system),是融合相机和IMU数据实现SLAM的算法,根据融合框架的区别又分为紧耦合和松耦合…

vivado VIO (virtual input output)虚拟IO的使用

转自:https://blog.csdn.net/wordwarwordwar/article/details/77150930 一般情况下ILA和VIO都是用在chipscope上使用,VIO可以作为在chipscope时模拟IO。 譬如: 在使用chipscope时需要使用按键出发,但是没有设计按键或者板子不再身…

【Vivado那些事儿】-VIO原理及应用

虚拟输入输出(Virtual Input Output,VIO)核是一个可定制的IP核,它可用于实时监视和驱动内部FPGA的信号,如图所示。 可以定制VIO的输入和输出端口的数量与宽度,用于和FPGA设计进行连接。由于VIO核与被监视和驱动的设计同步&#xf…