Elasticsearch:wildcard - 通配符搜索

Elasticsearch 是一个分布式、免费和开放的搜索和分析引擎,适用于所有类型的数据,例如文本、数字、地理空间、结构化和非结构化数据。 它基于 Apache Lucene 构建,Apache Lucene 是一个全文搜索引擎,可用于各种编程语言。 由于其速度、可扩展性以及对不同类型内容进行索引的能力,Elasticsearch 已在多种用例中得到应用,例如:

  • 企业搜索
  • 日志记录和日志分析
  • 应用搜索
  • 商业分析
  • 地理空间数据分析和可视化

它是如何工作的?

Elasticsearch 不是将信息存储为列式数据行,而是存储已序列化为 JSON 文档的复杂数据结构。 每个文档由一组键(文档中的字段或属性的名称)及其相应的值(字符串、数字、布尔值、日期、值数组、地理位置或其他类型的数据)组成。 它使用一种称为倒排索引的数据结构,列出任何文档中出现的每个唯一单词,并标识每个单词出现的所有文档。

字段类型 - 分析或未分析

Elasticsearch 中的字符串文字要么被分析,要么未被分析。 那么分析到底是什么意思呢? 已分析字段是指在索引之前经过分析过程的字段。 然后,该分析的结果存储在倒排索引中。 分析过程基本上涉及对文本块进行分词和规范化。 这些字段被分词为术语,并且术语被转换为小写字母。 这是标准分析器的行为,也是默认行为。 但是,如果需要,我们可以指定我们自己的分析器,例如,如果你还想索引特殊字符,而标准分析器则不会这样做。如果你想对 analyzer 有更多的了解,请阅读文章 “Elasticsearch: analyzer”。

我们尝试使用如下的命令来进行分词:

GET _analyze
{"analyzer": "standard","text" : "Beijing is a beautiful city"
}

Elasticsearch 的标准分析器会将此文本转换为以下内容:

{"tokens": [{"token": "beijing","start_offset": 0,"end_offset": 7,"type": "<ALPHANUM>","position": 0},{"token": "is","start_offset": 8,"end_offset": 10,"type": "<ALPHANUM>","position": 1},{"token": "a","start_offset": 11,"end_offset": 12,"type": "<ALPHANUM>","position": 2},{"token": "beautiful","start_offset": 13,"end_offset": 22,"type": "<ALPHANUM>","position": 3},{"token": "city","start_offset": 23,"end_offset": 27,"type": "<ALPHANUM>","position": 4}]
}

通配符(wildcard)搜索快速介绍

通配符是特殊字符,充当文本值中未知字符的占位符,并且可以方便地查找具有相似但不相同数据的多个项目。 通配符搜索基于查询中提到的字符与包含这些字符模式的文档中的单词之间的字符模式匹配。

查找名字/姓氏为 John 的每个人

现在我们已经基本了解了 Elasticsearch 的工作原理、分析字段和通配符搜索是什么,让我们更深入地了解本文的主题 — 字符串字段并对其运行通配符搜索。

字符串字段和通配符搜索

Elasticsearch 中的每个字段都有一个字段数据类型。 此类型指示字段包含的数据类型(例如字符串或布尔值)及其预期用途。 Elasticsearch 中可用于字符串的两种字段类型是 — text(默认)和 keyword。 它们之间的主要区别在于,文本字段在索引时进行分析,而关键字字段则不然。 这意味着,文本字段在索引之前会被标准化并分解为单独的分词,而关键字字段则按原样存储。 此外,由于文本字段已标准化,因此它们支持不区分大小写的搜索。 为了对关键字字段实现相同的效果,我们必须在创建索引时定义一个 normalizer,然后在定义字段映射时指定相同的 normalizer。有关 nomalizer 的详细介绍,请阅读文章 “Elasticsearch:词分析中的 Normalizer 的使用”。

PUT wildcard
{"settings": {"analysis": {"normalizer": {"lowercase_normalizer": {"type": "custom","char_filter": [],"filter": ["lowercase","asciifolding"]}}}},"mappings": {"properties": {"text-field": {"type": "text"},"keyword-field": {"type": "keyword","normalizer": "lowercase_normalizer"}}}
}

现在进行通配符查询,假设我们有以下文档,并且我们想要对其运行一些通配符搜索:

PUT wildcard/_doc/1
{"text-field": "Mockingbirds don’t do one thing but make music for us to enjoy.","keyword-field": "Mockingbirds don’t do one thing but make music for us to enjoy."
}

如下所示的查询可以很好地处理文本字段:

GET wildcard/_search?filter_path=**.hits
{"_source": false, "fields": ["text-field"], "query": {"wildcard": {"text-field": {"value": "*birds*"}}}
}

上面的搜索返回结果:

{"hits": {"hits": [{"_index": "wildcard","_id": "1","_score": 1,"fields": {"text-field": ["Mockingbirds don’t do one thing but make music for us to enjoy."]}}]}
}

然而,下面的搜索则不会:

GET wildcard/_search?filter_path=**.hits
{"_source": false, "fields": ["text-field"], "query": {"wildcard": {"text-field": {"value": "*birds*music*"}}}
}

它返回的结果是:

{"hits": {"hits": []}
}

原因是,该字段的单词已被分析并存储为分词。 因此,elasticsearch 无法找到与给定表达式(*birds*music*)对应的分词。

但是,这适用于关键字字段,因为它们按原样存储。我们来尝试如下的搜索:

GET wildcard/_search?filter_path=**.hits
{"_source": false,"fields": ["keyword-field"],"query": {"wildcard": {"keyword-field": {"value": "*birds*music*"}}}
}

上面的命令返回的结果是:

{"hits": {"hits": [{"_index": "wildcard","_id": "1","_score": 1,"fields": {"keyword-field": ["mockingbirds don't do one thing but make music for us to enjoy."]}}]}
}

现在,让我们讨论从 ElasticSearch v7.9 引入的另一个字符串字段——通配符。 这是一种专门的字段类型,主要用于非结构化机器生成的内容。更多阅读,请参阅文章 “Elasticsearch:使用新的 wildcard 字段更快地在字符串中查找字符串 - 7.9 新功能”。

以下是对这 3 种字段类型运行几个通配符查询的性能统计数据:

Query : *Elasticsearch* — Full word search

Query : *Wal* — Substring search

Query : *Elastic*stash* — Search across multiple words

我们可以清楚地看到,关键字字段的性能在所有搜索查询和索引大小中是最一致的。 文本字段也做得不错,但它们不能用于搜索像 *Elastic*stash* 这样的值,这使得关键字类型成为明显的赢家。

那么为什么要引入通配符字段呢? 那么,引入通配符字段是为了解决文本和关键字字段存在的以下限制:

  • 文本字段 - 将任何通配符表达式的匹配限制为单个分词,而不是字段中保存的原始整个值。
  • 关键字字段 - 当搜索子字符串和有许多唯一值时,关键字字段的速度很慢。 关键字字段还存在数据大小限制的缺点。 默认字符串映射会忽略长度超过 256 个字符的字符串。 这可以扩展到单个令牌 32k 的 Lucene 硬限制。 当您尝试搜索系统日志和类似文档时,这可能会产生问题。

通配符字段解决了上述限制。 它不会将字符串视为由标点符号分隔的标记集合,而是通过首先对所有文档进行近似匹配,然后对通过匹配接收到的文档子集应用详细比较来执行模式匹配。

文本、关键字和通配符字段之间的详细比较可以在此处阅读。

上述统计信息是通过在 v8.9 上运行的 elasticsearch 索引上运行搜索获得的,映射如下:

{"wildcard-search-demo-index": {"mappings": {"properties": {"field1": {"type": "text"},"field2": {"type": "keyword"},"field3": {"type": "wildcard"}}}}
}

索引的文档在所有字段中具有统一的数据,即文档中的所有 3 个字段都具有相同的值。 例如,

"hits": [{"_index": "wildcard-search-demo-index","_type": "_doc","_id": "vlPiHYYB6ikeelRg4I8n","_score": 1.0,"_source": {"field1": "It started as a scalable version of the Lucene open-source search framework then added the ability to horizontally scale Lucene indices.","field2": "It started as a scalable version of the Lucene open-source search framework then added the ability to horizontally scale Lucene indices.","field3": "It started as a scalable version of the Lucene open-source search framework then added the ability to horizontally scale Lucene indices."}},{"_index": "wildcard-search-demo-index","_type": "_doc","_id": "v1PiHYYB6ikeelRg4I87","_score": 1.0,"_source": {"field1": "Elasticsearch allows you to store, search, and analyze huge volumes of data quickly and in near real-time and give back answers in milliseconds.","field2": "Elasticsearch allows you to store, search, and analyze huge volumes of data quickly and in near real-time and give back answers in milliseconds.","field3": "Elasticsearch allows you to store, search, and analyze huge volumes of data quickly and in near real-time and give back answers in milliseconds."}}]

综上所述,字段类型的选择并没有固定的规则。 它取决于多种因素,例如数据类型、必须涵盖的不同用例集等。

在设置数据存储时,决定字段类型是一个非常关键的因素,因为它极大地影响性能,并且应该通过考虑所有可能的场景和因素来决定。

Elasticsearch 还有一种称为通配符的查询类型,可用于运行通配符查询。 

另外值得指出的是:由于通配符搜索带来很多的性能问题,有时甚至会吃掉很多的系统资源。在生成环境中,有的建议关掉这个功能以避免影响系统的运行。建议阅读文章:

  • Kibana:如何在 Kibana 中禁止查询中使用前置通配符(wildcard)查询

  • Elasticsearch:如何提高查询性能

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/97363.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HBase集群环境搭建与测试

&#x1f947;&#x1f947;【大数据学习记录篇】-持续更新中~&#x1f947;&#x1f947; 个人主页&#xff1a;beixi 本文章收录于专栏&#xff08;点击传送&#xff09;&#xff1a;【大数据学习】 &#x1f493;&#x1f493;持续更新中&#xff0c;感谢各位前辈朋友们支持…

Java 多线程系列Ⅳ(单例模式+阻塞式队列+定时器+线程池)

多线程案例 一、设计模式&#xff08;单例模式工厂模式&#xff09;1、单例模式2、工厂模式 二、阻塞式队列1、生产者消费者模型2、阻塞对列在生产者消费者之间的作用3、用标准库阻塞队列实现生产者消费者模型4、模拟实现阻塞队列 三、定时器1、标准库中的定时器2、模拟实现定时…

go语言基本操作---三

变量的内存和变量的地址 指针是一个代表着某个内存地址的值。这个内存地址往往是在内存中存储的另一个变量的值的起始位置。Go语言对指针的支持介于java语言和C/C语言之间&#xff0c;它即没有想Java语言那样取消了代码对指针的直接操作的能力&#xff0c;也避免了C/C语言中由…

视频监控/视频汇聚/视频云存储EasyCVR平台接入华为ivs3800平台提示400报错,该如何解决?

开源EasyDarwin视频监控TSINGSEE青犀视频平台EasyCVR能在复杂的网络环境中&#xff0c;将分散的各类视频资源进行统一汇聚、整合、集中管理&#xff0c;在视频监控播放上&#xff0c;视频云存储/安防监控汇聚平台可支持1、4、9、16个画面窗口播放&#xff0c;可同时播放多路视频…

【mybatis-plus】多数据源切换[dynamic-datasource] 手动切换数据源

Springbootmybatis-plusdynamic-datasourceDruid 手动切换数据源 文章目录 Springbootmybatis-plusdynamic-datasourceDruid 手动切换数据源0.前言1. 多数据源核心类浅析1. 1. DynamicDataSourceContextHolder切换数据源核心类1.2. DynamicRoutingDataSource 2.基于核心类的理解…

锁( ReentrantLock,Synchronized)

1.lock和synchronized 语法层面 synchronized 是关键字&#xff0c;源码在 jvm 中&#xff0c;用 c 语言实现&#xff1b; Lock 是接口&#xff0c;源码由 jdk 提供&#xff0c;用 java 语言实现&#xff1b; 使用 synchronized 时&#xff0c;退出同步代码块锁会自动释放&…

Java 复习笔记 - 学生管理系统篇

文章目录 学生管理系统一&#xff0c;需求部分需求分析初始菜单学生类添加功能删除功能修改功能查询功能 二&#xff0c;实现部分&#xff08;一&#xff09;初始化主界面&#xff08;二&#xff09;编写学生类&#xff08;三&#xff09;编写添加学生方法&#xff08;四&#…

Nginx 配置中root和alias的区别分析

root和alias都可以定义在location模块中&#xff0c;都是用来指定请求资源的真实路径&#xff0c;比如&#xff1a; location /i/ { root /data/w3; } 请求 http://foofish.net/i/top.gif 这个地址时&#xff0c;那么在服务器里面对应的真正的资源 是 /data/w3/i/top.gif文…

2023年03月 C/C++(七级)真题解析#中国电子学会#全国青少年软件编程等级考试

C/C编程&#xff08;1~8级&#xff09;全部真题・点这里 第1题&#xff1a;走出迷宫 当你站在一个迷宫里的时候&#xff0c;往往会被错综复杂的道路弄得失去方向感&#xff0c;如果你能得到迷宫地图&#xff0c;事情就会变得非常简单。 假设你已经得到了一个n*m的迷宫的图纸&a…

移动零00

题目链接 移动零 题目描述 注意点 将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序必须在不复制数组的情况下原地对数组进行操作 解答思路 采用双指针的思路&#xff0c;左指针指向已移动零的数组的尾部&#xff0c;右指针指向为移动零的数组的头部&…

Android-关于页面卡顿的排查工具与监测方案

作者&#xff1a;一碗清汤面 前言 关于卡顿这件事已经是老生常谈了&#xff0c;卡顿对于用户来说是敏感的&#xff0c;容易被用户直接感受到的。那么究其原因&#xff0c;卡顿该如何定义&#xff0c;对于卡顿的发生该如何排查问题&#xff0c;当线上用户卡顿时&#xff0c;在线…

宝塔面板一键部署Z-Blog博客 - 内网穿透实现公网访问

文章目录 1.前言2.网站搭建2.1. 网页下载和安装2.2.网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar临时数据隧道3.2.Cpolar稳定隧道&#xff08;云端设置&#xff09;3.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 4.公网访问测试5.结语 1.前言 Ubuntu系统作…