中间件之搜索和数据分析组件Elasticsearch
The Elastic Stack, 包括 Elasticsearch、Kibana、Beats 和 Logstash(也称为 ELK Stack)。 能够安全可靠地获取任何来源、任何格式的数据,然后实时地对数据进行搜索、分析和可视 化。Elaticsearch,简称为 ES,ES 是一个开源的高扩展的分布式全文搜索引擎,是整个 Elastic Stack 技术栈的核心。它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上 百台服务器,处理 PB 级别的数据。
Elasticsearch是由elastic公司开发的一套搜索引擎技术,它是elastic技术栈中的一部分。完整的技术栈包括:
整套技术栈被称为ELK,经常用来做日志收集、系统监控和状态分析等等:
Google,百度类的网站搜索,它们都是根据网页中的关键字生成索引,我们在搜索的时 候输入关键字,它们会将该关键字即索引匹配到的所有网页返回;还有常见的项目中应用日 志的搜索等等。对于这些非结构化的数据文本,关系型数据库搜索不是能很好的支持。全文搜索引擎
全⽂检索 是计算机程序通过扫描⽂章中的 每⼀个词,对每⼀个词建⽴⼀个索 引,指明该词在⽂章中出现的次数和位置 。当⽤户 查询时根据建⽴的索引查找 , 类似于通过字典的检索字表查字的过程
索: 建⽴索引 ⽂本---->切分 ---> 词 ⽂章出现过 出现多少次
检索: 查询 关键词---> 索引中--> 符合条件⽂章 相关度排序
全⽂检索(Full-Text Retrieval)以⽂本作为检索对象,找出含有指定词汇的⽂ 本。全⾯、准确和快速是衡量全⽂检索系统的关键指标
- 只处理⽂本、不处理语义
- 搜索时英⽂不区分⼤⼩写
- 结果列表有相关度排序
Lucene 是 Apache 软件基金会 Jakarta 项目组的一个子项目,提供了一个简单却强大的 应用程式接口,能够做全文索引和搜寻。在 Java 开发环境里 Lucene 是一个成熟的免费开源 工具。就其本身而言,Lucene 是当前以及最近几年最受欢迎的免费 Java 信息检索程序库。 但 Lucene 只是一个提供全文搜索功能类库的核心工具包,而真正使用它还需要一个完善的 服务框架搭建起来进行应用。
目前市面上流行的搜索引擎软件,主流的就两款:Elasticsearch 和 Solr,这两款都是基 于 Lucene 搭建的,可以独立部署启动的搜索引擎服务软件。由于内核相同,所以两者除了 服务器安装、部署、管理、集群以外,对于数据的操作 修改、添加、保存、查询等等都十 分类似。
在使用过程中,一般都会将 Elasticsearch 和 Solr 这两个软件对比,然后进行选型。这两 个搜索引擎都是流行的,先进的的开源搜索引擎。它们都是围绕核心底层搜索库 - Lucene 构建的 - 但它们又是不同的。像所有东西一样,每个都有其优点和缺点:
ElasticSearch
ElasticSearch 简称 ES ,是基于 Apache Lucene 构建的 开源搜索引 擎 ,是当前最流⾏的 企业级搜索引擎 。 Lucene本身就可以被认为迄今为⽌性 能最好的⼀款开源搜索引擎⼯具包 ,但是lucene的API相对复杂,需要深厚的 搜索理论。很难集成到实际的应⽤中去。 ES是采⽤java语⾔编写,提供了简 单易⽤的RestFul API,开发者可以使⽤其简单的RestFul API,开发相关的搜 索功能,从⽽避免lucene的复杂性
注意,这里我们采用的是elasticsearch的7.12.1版本,由于8以上版本的JavaAPI变化很大,在企业中应用并不广泛,企业中应用较多的还是8以下的版本。
进入容器内部
Kibana
Kibana Navicat 是⼀个针对 Elasticsearch mysql 的 开源分析及可视化 平台 ,使⽤Kibana可以 查询、查看并与存储在ES索引的数据进⾏交互操作 ,使 ⽤Kibana能执⾏⾼级的 数据分析,并能以图表、表格和地图的形式查看数据
安装完成后,直接访问5601端口,即可看到控制台页面:
选择之后,进入主页面:
然后选中,进入开发工具页面:
索引
⼀个索引就是⼀个拥有⼏分相似特征的⽂档的集合 。⽐如说,你可以有⼀个 商品数据的索引,⼀个订单数据的索引,还有⼀个⽤户数据的索引。 ⼀个 索引由⼀个名字来标识 (必须全部是⼩写字⺟的) ,并且当我们要对这个索引 中的⽂档进⾏索引、搜索、更新和删除的时候,都要使⽤到这个名字
随着业务发展,需要在es中存储的文档也会越来越多,比如有商品的文档、用户的文档、订单文档等等:
所有文档都散乱存放显然非常混乱,也不方便管理。
因此,我们要将类型相同的文档集中在一起管理,称为索引(Index)。例如:
映射
映射是定义⼀个⽂档和它所包含的字段如何被存储和索引的过程 。在默认配 置下,ES可以根据插⼊的数据 ⾃动地创建mapping,也可以⼿动创建 mapping 。 mapping中主要包括字段名、字段类型等
数据库的表会有约束信息,用来定义表的结构、字段的名称、类型等信息。因此,索引库中就有映射(mapping),是索引中文档的字段约束信息,类似表的结构约束。
⽂档
⽂档是索引中存储的⼀条条数据。⼀条⽂档是⼀个可被索引的最⼩单元 。ES 中的⽂档采⽤了轻量级的JSON格式数据来表示。
elasticsearch是面向文档(document)存储的,可以是数据库中的一条商品数据,一个订单信息。文档数据会被序列化为格式后存储在中:
Elasticsearch | 说明 | Table | Index | 索引(index),就是文档的集合,类似数据库的表(table) |
Row | document | 文档(document),就是一条条的数据,类似数据库中的行(Row),文档都是JSON格式 |
Column | Field | 字段(Field),就是JSON文档中的字段,类似数据库中的列(Column) |
Schema | Mapping | Mapping(映射)是索引中文档的约束,例如字段类型约束。类似数据库的表结构(Schema) |
SQL | DSL | DSL是elasticsearch提供的JSON风格的请求语句,用来操作elasticsearch,实现CRUD |
那是不是说,我们学习了elasticsearch就不再需要mysql了呢?
并不是如此,两者各自有自己的擅长之处:
因此在企业中,往往是两者结合使用:
elasticsearch之所以有如此高性能的搜索表现,正是得益于底层的倒排索引技术。那么什么是倒排索引呢?
倒排索引的概念是基于MySQL这样的正向索引而言的。
正向索引
我们先来回顾一下正向索引。
例如有一张名为的表:
id | title | price |
---|
1 | 小米手机 | 3499 |
2 | 华为手机 | 4999 |
3 | 华为小米充电器 | 49 |
4 | 小米手环 | 49 |
... | ... | ... |
其中的字段已经创建了索引,由于索引底层采用了B+树结构,因此我们根据id搜索的速度会非常快。但是其他字段例如,只在叶子节点上存在。
因此要根据搜索的时候只能遍历树中的每一个叶子节点,判断title数据是否符合要求。
比如用户的SQL语句为:
综上,根据id精确匹配时,可以走索引,查询效率较高。而当搜索条件为模糊匹配时,由于索引无法生效,导致从索引查询退化为全表扫描,效率很差。
因此,正向索引适合于根据索引字段的精确搜索,不适合基于部分词条的模糊匹配。
而倒排索引恰好解决的就是根据部分词条模糊匹配的问题。
倒排索引
倒排索引中有两个非常重要的概念:
创建倒排索引是对正向索引的一种特殊处理和应用,流程如下:
此时形成的这张以词条为索引的表,就是倒排索引表,两者对比如下:
倒排索引的搜索流程如下(以搜索"华为手机"为例),如图:
正向索引是最传统的,根据id索引的方式。但根据词条查询时,必须先逐条获取每个文档,然后判断文档中是否包含所需要的词条,是根据文档找词条的过程。
而倒排索引则相反,是先找到用户要搜索的词条,根据词条得到保护词条的文档的id,然后根据id获取文档。是根据词条找文档的过程。
正向索引:
-
可以给多个字段创建索引
-
根据索引字段搜索、排序速度非常快
缺点:
倒排索引:
缺点:
-
只能给词条创建索引,而不是字段
-
无法根据字段做排序
Analysis 和 Analyzer
Analysis : ⽂本分析是把全⽂本转换⼀系列单词(term/token)的过程,也 叫分词(Analyzer)。Analysis是通过Analyzer来实现的。 分词就是将⽂档通过 Analyzer分成⼀个⼀个的Term(关键词查询),每⼀个Term都指向包含这个Term 的⽂档
Analyzer 组成 注意: 在ES中默认使⽤标准分词器: StandardAnalyzer 特点: 中⽂单字分 词 单词分词 我是中国⼈ this is good man----> analyzer----> 我 是 中 国 ⼈ this is good man
Analyzer 组成
注意: 在ES中默认使⽤标准分词器: StandardAnalyzer 特点: 中⽂单字分 词 单词分词
我是中国⼈ this is good man----> analyzer----> 我 是 中 国 ⼈ this is good man
分析器(analyzer)都由三种构件组成的: character filters , tokenizers , token filters 。
- 三者顺序: Character Filters--->Tokenizer--->Token Filter
- 三者个数:Character Filters(0个或多个) + Tokenizer + Token Filters(0 个或多个
内置分词器
- Standard Analyzer - 默认分词器,英⽂按单词词切分,并⼩写处理
- Simple Analyzer - 按照单词切分(符号被过滤), ⼩写处理
- Stop Analyzer - ⼩写处理,停⽤词过滤(the,a,is)
- Whitespace Analyzer - 按照空格切分,不转⼩写
- Keyword Analyzer - 不分词,直接将输⼊当作输出
内置分词器测试
标准分词器
特点: 按照单词分词 英⽂统⼀转为⼩写 过滤标点符号 中⽂单字分词
Simple 分词器
特点: 英⽂按照单词分词 英⽂统⼀转为⼩写 去掉符号 中⽂按照空格 进⾏分词
Whitespace 分词器
特点: 中⽂ 英⽂ 按照空格分词 英⽂不会转为⼩写 不去掉标点符号
创建索引设置分词
中⽂分词器
在ES中⽀持中⽂分词器⾮常多 如 smartCN、IK 等,推荐的就是 IK分词 器
然后重启es容器:
IK分词器包含两种模式:
拓展词典
随着互联网的发展,“造词运动”也越发的频繁。出现了很多新的词语,在原有的词汇列表中并不存在。比如:“泰裤辣”,“传智播客” 等。
IK分词器如何拓展词条?如何停用词条?
-
利用config目录的文件添加拓展词典和停用词典
-
在词典中添加拓展词条或者停用词条
Index就类似数据库表,Mapping映射就类似表的结构。我们要向es中存储数据,必须先创建Index和Mapping
Mapping是对索引库中文档的约束,常见的Mapping属性包括:
说明: ES中⽀持字段类型⾮常丰富,如:text、keyword、integer、 long、ip 等。更多参⻅https://www.elastic.co/guide/en/elasticsearch/re ference/7.15/mapping-types.html
创建索引库和映射
-
请求方式:
-
请求路径:,可以自定义
-
请求参数:映射
查询索引库
-
请求方式:GET
-
请求路径:/索引库名
-
请求参数:无
查看所有索引
修改索引库
倒排索引结构虽然不复杂,但是一旦数据结构改变(比如改变了分词器),就需要重新创建倒排索引,这简直是灾难。因此索引库一旦创建,无法修改mapping。
虽然无法修改mapping中已有的字段,但是却允许添加新的字段到mapping中,因为不会对倒排索引产生影响。因此修改索引库能做的就是向索引库中添加新字段,或者更新索引库的基础属性。
语法说明:
-
请求方式:DELETE
-
请求路径:/索引库名
-
请求参数:无
格式:
示例:
查询
有了索引库,接下来就可以向索引库中添加数据了。
Elasticsearch中的数据其实就是JSON风格的文档。操作文档自然保护、、、等几种常见操作,我们分别来学习。
新增文档
注意
根据rest风格,新增是post,查询应该是get,不过查询一般都需要条件,这里我们把文档id带上。
查询所有文档
在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search
删除文档
删除使用DELETE请求,同样,需要根据id进行删除:
删除一个文档不会立即从磁盘上移除,它只是被标记成已删除(逻辑删除)。
条件删除文档
一般删除数据都是根据文档的唯一性标识进行删除,实际操作时,也可以根据条件对多条数 据进行删除
向 ES 服务器发 POST 请求
修改文档
修改有两种方式:
-
全量修改:直接覆盖原来的文档
-
局部修改:修改文档中的部分字段
全量修改
全量修改是覆盖原来的文档,其本质是两步操作:
注意:如果根据id删除时,id不存在,第二步的新增也会执行,也就从修改变成了新增操作了。
局部修改
局部修改是只修改指定id匹配的文档中的部分字段。
批处理
批处理采用POST请求,基本语法如下:
其中:
-
代表新增操作
-
:指定索引库名
-
指定要操作的文档id
-
:则是要新增的文档内容
-
代表删除操作
-
代表更新操作
-
:指定索引库名
-
指定要操作的文档id
-
:要更新的文档字段
示例,批量新增:
批量删除:
说明:批量时不会因为⼀个失败⽽全部失败,⽽是继续执⾏后续操作,在返 回时按照执⾏的状态返回
ES中提供了⼀种强⼤的检索数据⽅式,这种检索⽅式称之为 Query DSL , Query DSL 是利⽤ Rest API传递JSON格式的请求体(Request Body)数据 与ES进⾏交互,这种⽅式的 丰富查询语法 让ES检索变得 更强⼤,更简洁
Elasticsearch的查询可以分为两大类:
快速入门
我们依然在Kibana的DevTools中学习查询的DSL语法。首先来看查询的语法结构:
说明:
你会发现虽然是match_all,但是响应结果中并不会包含索引库中的所有文档,而是仅有10条。这是因为处于安全考虑,elasticsearch设置了默认的查询页数。
叶子查询的类型也可以做进一步细分,详情大家可以查看官方文档:
https://www.elastic.co/guide/en/elasticsearch/reference/7.12/query-dsl.html
这里列举一些常见的,例如:
-
全文检索查询(Full Text Queries):利用分词器对用户输入搜索条件先分词,得到词条,然后再利用倒排索引搜索词条。例如:
-
精确查询(Term-level queries):不对用户输入搜索条件分词,根据字段内容精确值匹配。但只能查找keyword、数值、日期、boolean类型的字段。例如:
-
地理坐标查询:用于搜索地理位置,搜索方式很多,例如:
--------------------------------------
全文检索查询
多字段查询[multi_match]
与类似的还有,区别在于可以同时对多个字段搜索,而且多个字段都要满足,语法示例:
查询所有[match_all]
match_all关键字: 返回索引中的全部⽂档
-------------------------------------
精确查询
精确查询,英文是,顾名思义,词条级别的查询。也就是说不会对用户输入的搜索条件再分词,而是作为一个词条,与搜索的字段内容精确值匹配。因此推荐查找、数值、日期、类型的字段。例如:
详情可以查看官方文档:
https://www.elastic.co/guide/en/elasticsearch/reference/7.12/term-level-queries.html
查询
以查询为例,其语法如下:
NOTE1: 通过使⽤term查询得知ES中默认使⽤分词器为 标准分词器 (StandardAnalyzer),标准分词器对于英⽂单词分词,对于中⽂单字分词
NOTE2: 通过使⽤term查询得知, 在ES的Mapping Type 中 keyword , date ,integer, long , double , boolean or ip 这些类型不分 词,只有text类型分词
当你输入的搜索条件不是词条,而是短语时,由于不做分词,你反而搜索不到:
范围查询[range]
是范围查询,对于范围筛选的关键字有:
前缀查询[prefix]
prefix 关键字: ⽤来检索含有指定前缀的关键词的相关⽂档
通配符查询[wildcard]
wildcard 关键字: 通配符查询 ? ⽤来匹配⼀个任意字符 * ⽤来匹配多个任意字符
多id查询[ids]
ids 关键字 : 值为数组类型,⽤来根据⼀组id获取多个对应的⽂档
模糊查询[fuzzy]
fuzzy 关键字: ⽤来模糊查询含有指定关键字的⽂档
返回包含与搜索字词相似的字词的文档。
编辑距离是将一个术语转换为另一个术语所需的一个字符更改的次数。这些更改可以包括: 更改字符(box → fox)
删除字符(black → lack)
插入字符(sic → sick)
转置两个相邻字符(act → cat)
为了找到相似的术语,fuzzy 查询会在指定的编辑距离内创建一组搜索词的所有可能的变体 或扩展。然后查询返回每个扩展的完全匹配。
通过 fuzziness 修改编辑距离。一般使用默认值 AUTO,根据术语的长度生成编辑距离。
因此,该查询的含义是在"products"索引中搜索描述字段("description")包与"iphooone"相似的文档。
{ "id": 1, "name": "iPhone X", "description": "The latest iPhone model with Face ID" }
默认字段分词查询[query_string]
假设在"products"索引中有以下文档:
- { "description": "这款手机的屏幕真的非常出色,色彩鲜艳且清晰。", "price": 5000 }
- { "description": "这台电脑的屏幕质量非常好,分辨率高,色彩还原度高。", "price": 8000 }
- { "description": "这台电视的屏幕效果非常棒,画质细腻,色彩饱满。", "price": 12000 }
- { "description": "这款相机的屏幕显示效果不错,可以实时预览拍摄画面。", "price": 3000 }
.复合查询
复合查询大致可以分为两类:
其它复合查询及相关语法可以参考官方文档:
https://www.elastic.co/guide/en/elasticsearch/reference/7.12/compound-queries.html
布尔查询[bool]
bool查询,即布尔查询。就是利用逻辑运算来组合一个或多个查询子句的组合。bool查询支持的逻辑运算有:
bool查询的语法如下:
过滤查询
过滤查询,其实准确来说,ES中的查询操作分为2种: 查询(query) 和 过滤 (filter) 。查询即是之前提到的 query查询 ,它 (查询)默认会计算每个返 回⽂档的得分,然后根据得分排序。⽽ 过滤(filter) 只会筛选出符合的⽂ 档,并不计算 得分,⽽且它可以缓存⽂档 。所以,单从性能考虑,过滤⽐ 查询更快。 换句话说 过滤适合在⼤范围筛选数据,⽽查询则适合精确匹配数 据。⼀般应⽤时, 应先使⽤过滤操作过滤数据, 然后使⽤查询匹配数据。
- 在执⾏ filter 和 query 时,先执⾏ filter 在执⾏
- query Elasticsearch会⾃动缓存经常使⽤的过滤器,以加快性能。
常⻅过滤类型有: term 、 terms 、ranage、exists、ids等filter。
算分函数查询
当我们利用match查询时,文档结果会根据与搜索词条的关联度打分(_score),返回结果时按照分值降序排列。
例如,我们搜索 "手机",结果如下:
从elasticsearch5.1开始,采用的相关性打分算法是BM25算法,公式如下:
基于这套公式,就可以判断出某个文档与用户搜索的关键字之间的关联度,还是比较准确的。但是,在实际业务需求中,常常会有竞价排名的功能。不是相关度越高排名越靠前,而是掏的钱多的排名靠前。
-
过滤条件:品牌必须为IPhone
-
算分函数:常量weight,值为10
-
算分模式:相乘multiply
对应代码如下:
排序
elasticsearch默认是根据相关度算分()来排序,但是也支持自定义方式对搜索结果排序。不过分词字段无法排序,能参与排序字段类型有:类型、数值类型、地理坐标类型、日期类型等。
详细说明可以参考官方文档:
https://www.elastic.co/guide/en/elasticsearch/reference/7.12/sort-search-results.html
语法说明:
返回指定字段[_source]
过滤字段
我们也可以通过:
includes:来指定想要显示的字段
excludes:来指定不想要显示的字段
多字段排序
分页
返回指定条数[size】
深度分页
elasticsearch的数据一般会采用分片存储,也就是把一个索引中的数据分成N份,存储到不同节点上。这种存储方式比较有利于数据扩展,但给分页带来了一些麻烦。
比如一个索引库中有100000条数据,分别存储到4个分片,每个分片25000条数据。现在每页查询10条,查询第99页。那么分页查询的条件如下:
从语句来分析,要查询第990~1000名的数据。
从实现思路来分析,肯定是将所有数据排序,找出前1000名,截取其中的990~1000的部分。但问题来了,我们如何才能找到所有数据中的前1000名呢?
要知道每一片的数据都不一样,第1片上的第900~1000,在另1个节点上并不一定依然是900~1000名。所以我们只能在每一个分片上都找出排名前1000的数据,然后汇总到一起,重新排序,才能找出整个索引库中真正的前1000名,此时截取990~1000的数据即可。
试想一下,假如我们现在要查询的是第999页数据呢,是不是要找第9990~10000的数据,那岂不是需要把每个分片中的前10000名数据都查询出来,汇总在一起,在内存中排序?如果查询的分页深度更深呢,需要一次检索的数据岂不是更多?
由此可知,当查询分页深度较大时,汇总数据过多,对内存和CPU会产生非常大的压力。
因此elasticsearch会禁止超过10000的请求。
针对深度分页,elasticsearch提供了两种解决方案:
详情见文档:
https://www.elastic.co/guide/en/elasticsearch/reference/7.12/paginate-search-results.html
总结:
大多数情况下,我们采用普通分页就可以了。查看百度、京东等网站,会发现其分页都有限制。例如百度最多支持77页,每页不足20条。京东最多100页,每页最多60条。
因此,一般我们采用限制分页深度的方式即可,无需实现深度分页。
在进行关键字搜索时,搜索出的内容中的关键字会显示不同的颜色,称之为高亮。
css样式肯定是前端实现页面的时候写好的,但是前端编写页面的时候是不知道页面要展示什么数据的,不可能给数据加标签。而服务端实现搜索功能,要是有做分词搜索,是知道哪些词条需要高亮的。
因此词条的高亮标签肯定是由服务端提供数据的时候已经加上的。
因此实现高亮的思路就是:
注意:
表示对所有字段进行高亮显示。
"post_tags": [""]表示在高亮显示的文本后面添加一个结束标签,即""。
"pre_tags": [""]表示在高亮显示的文本前面添加一个开始标签,即""。
这两个标签用于将高亮显示的文本包裹起来,以便在显示时能够以红色字体突出显示。
多字段⾼亮 使⽤ require_field_match 开启多个字段⾼亮
聚合:英⽂为Aggregation,是es除搜索功能外提供的针对es数据做统计分 析的功能。聚合有助于根据搜索查询提供聚合数据。聚合查询是数据库中 重要的功能特性,ES作为搜索引擎兼数据库,同样提供了强⼤的聚合分析 能⼒。它基于查询条件来对数据进⾏分桶、计算的⽅法。有点类似于 SQL 中的 group by 再加⼀些函数⽅法的操作
聚合()可以让我们极其方便的实现对数据的统计、分析、运算。例如:
-
什么品牌的手机最受欢迎?
-
这些手机的平均价格、最高价格、最低价格?
-
这些手机每月的销售情况如何?
实现这些统计功能的比数据库的sql要方便的多,而且查询速度非常快,可以实现近实时搜索效果。
官方文档:
https://www.elastic.co/guide/en/elasticsearch/reference/7.12/search-aggregations.html
注意:参加聚合的字段必须是keyword、日期、数值、布尔类型
注意事项:text类型是不⽀持聚合的
测试数据
Bucket聚合
例如我们要统计所有商品中共有哪些商品分类,其实就是以分类(category)字段对数据分组。category值一样的放在同一组,属于聚合中的聚合。
基本语法如下:
带条件聚合
默认情况下,Bucket聚合是对索引库的所有文档做聚合,例如我们统计商品中所有的品牌,结果如下:
但真实场景下,用户会输入搜索条件,因此聚合必须是对搜索结果聚合。那么聚合必须添加限定条件。
例如,我想知道价格高于3000元的手机品牌有哪些,该怎么统计呢?
我们需要从需求中分析出搜索查询的条件和聚合的目标:
语法如下:
Metric聚合
我们统计了价格高于3000的手机品牌,形成了一个个桶。现在我们需要对桶内的商品做运算,获取每个品牌价格的最小值、最大值、平均值。
这就要用到聚合了,例如聚合,就可以同时获取、、等结果。
求最⼤值
初始化RestClient
ES官方提供了各种不同语言的客户端,用来操作ES。这些客户端的本质就是组装DSL语句,通过http请求发送给ES。
官方文档地址:
Elasticsearch Clients | Elastic
由于ES目前最新版本是8.8,提供了全新版本的客户端,老版本的客户端已经被标记为过时。而我们采用的是7.12版本,因此只能使用老版本客户端:RestAPI
测试
创建索引库
由于要实现对商品搜索,所以我们需要将商品添加到Elasticsearch中,不过需要根据搜索业务的需求来设定索引库结构,而不是一股脑的把MySQL数据写入Elasticsearch.
创建索引
判断索引库是否存在
JavaRestClient操作elasticsearch的流程基本类似。核心是方法来获取索引库的操作对象。
索引库操作的基本步骤:
-
初始化
-
创建XxxIndexRequest。XXX是、、
-
准备请求参数( 时需要,其它是无参,可以省略)
-
发送请求。调用方法,xxx是、、
索引库准备好以后,就可以操作文档了。为了与索引库操作分离,我们再次创建一个测试类,做两件事情:
.新增文档
实体类
删除文档
修改文档
修改我们讲过两种方式:
-
全量修改:本质是先根据id删除,再新增
-
局部修改:修改文档中的指定字段值
在RestClient的API中,全量修改与新增的API完全一致,判断依据是ID:
-
如果新增时,ID已经存在,则修改
-
如果新增时,ID不存在,则新增
这里不再赘述,我们主要关注局部修改的API即可
新增文档
查询文档
修改文档
批量导入文档
在之前的案例中,我们都是操作单个文档。而数据库中的商品数据实际会达到数十万条,某些项目中可能达到数百万条。
我们如果要将这些数据导入索引库,肯定不能逐条导入,而是采用批处理方案。常见的方案有:
-
利用Logstash批量导入
-
需要安装Logstash
-
对数据的再加工能力较弱
-
无需编码,但要学习编写Logstash导入配置
-
利用JavaAPI批量导入
-
需要编码,但基于JavaAPI,学习成本低
-
更加灵活,可以任意对数据做再加工处理后写入索引库
语法说明
本身其实并没有请求参数,其本质就是将多个普通的CRUD请求组合在一起发送。例如:
可以看到,能添加的请求有:
这里关键的API有两个,一个是,它构建的就是DSL中的完整JSON参数。其中包含了、、、、等所有功能:
另一个是,其中包含了我们学习过的各种叶子查询、复合查询等:
所有的查询条件都是由QueryBuilders来构建的,叶子查询也不例外。因此整套代码中变化的部分仅仅是query条件构造的方式,其它不动。
例如查询:
再比如查询:
复合查询
复合查询也是由来构建,我们以查询为例,DSL和JavaAPI的对比如图:
排序和分页
高亮
高亮查询与前面的查询有两点不同:
可以看到在DSL中,聚合条件与条件是同一级别,都属于查询JSON参数。因此依然是利用方法来设置。
聚合必须的三要素:
聚合可配置属性有:
-
size:指定聚合结果数量
-
order:指定聚合结果排序方式
-
field:指定聚合字段
不过聚合条件的要利用这个工具类来构造。DSL与JavaAPI的语法对比如下:
聚合结果与搜索文档同一级别,因此需要单独获取和解析。具体解析语法如下:
配置客户端
客户端对象
- ElasticsearchOperations
- RestHighLevelClient 推荐
问题
创建索引⽂档
查询⽂档
查询所有
删除⽂档
删除所有
创建索引映射
其他同RestClient操作文档
本文地址:http://nhjcxspj.xhstdz.com/quote/464.html
物流园资讯网 http://nhjcxspj.xhstdz.com/ , 查看更多