目录
一. ElasticSearch背景
1.1 Elasticsearch介绍
1.2 Elasticsearch现状
1.3 Es最佳实践
二. 环境配置安装
2.1 Elasticsearch安装
2.2 配置ElasticSearch-head
2.3 配置Kibana
2.4 IK分词器依赖支持
三. ES功能使用
3.1 索引库操作
3.2 类型(type)及映射(mapping)操作
四. 请求体查询
4.1.基本查询
4.2.结果过滤
4.3.高级查询
4.4.查询排序
4.5.分页查询
五. ElasticSearch Java API客户端
5.1 客户端开发环境搭建
5.2 创建索引索引库
5.3 配置映射
5.4 文档操作
总结
一. ElasticSearch背景
1.1 Elasticsearch介绍
Elaticsearch,简称为es, es是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的检索数据;本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。ES使用Java开发。Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。
1.2 Elasticsearch现状
百度:百度目前广泛使用Elasticsearch作为文本数据分析,采集百度所有服务器上的各类指标数据及用户自定义数据,通过对各种数据进行多维分析展示,辅助定位分析实例异常或业务层面异常。目前覆盖百度内部20多个业务线(包括casio、云分析、网盟、预测、文库、直达号、钱包、风控等),单集群最大100台机器,200个ES节点,每天导入30TB+数据
新浪使用ES 分析处理32亿条实时日志
阿里使用ES 构建挖财自己的日志采集和分析体系
2013年初,GitHub抛弃了Solr,采用Elasticsearch 来做PB级的搜索。 “GitHub使用Elasticsearch
搜索20TB的数据,包括13亿文件和1300亿行代码”
维基百科:启动以Elasticsearch为基础的核心搜索架构
SoundCloud:“SoundCloud使用Elasticsearch为1.8亿用户提供即时而精准的音乐搜索服务”
1.3 Es最佳实践
企业使用场景一般分为2种情况:
1、在线运维系统:
模块搜索功能使用数据库查询实现,但是已经出现性能问题,或者不满足产品的高亮相关度排序需求
时。这种情况就会对系统的查询功能进行技术改造,转而使用全文检索,而es就是首选。改造业务流程
如图:
2、可插加式功能:
产品一开始就要实现高亮相关度排序等全文检索的功能。针对这种情况,企业实现功能业务流程如图:
3、索引库存的作用
索引库的数据是用来搜索用的,里面存储的数据和数据库一般不会是完全一样的,一般都比数据库的数
据少。
那索引库存什么数据呢?
以业务需求为准,需求决定页面要显示什么字段以及会按什么字段进行搜索,那么这些字段就都要保存
到索引库中。
二. 环境配置安装
2.1 Elasticsearch安装
1、ES下载
目前Elasticsearch最新的版本是7.4.2,我们使用6.8.0版本,建议使用JDK1.8及以上
Elasticsearch分为Linux和Window版本,基于我们主要学习的是Elasticsearch的Java客户端的使用,所
以我们课程中使用的是安装较为简便的Window版本,项目上线后,公司的运维人员会安装Linux版的
ES供我们连接使用。
Elasticsearch的官方地址:https://www.elastic.co/cn/downloads/past-releases
2、启动ES配置
Window版的Elasticsearch的安装很简单,类似Window版的Tomcat,解压开即安装完毕,解压后的
Elasticsearch的目录结构如下:
3、启动ES命令
点击Elasticsearch下的bin目录下的Elasticsearch.bat启动,控制台显示的日志信息如下:
注意:9300是tcp通讯端口,集群间和TCP 客户端都执行该端口,9200是http协议的RESTful接口 。
通过浏览器访问Elasticsearch服务器,看到如下返回的json信息,代表服务启动成功:
ElasticSearch6.8.0默认占用本机内存1个G,如果不足,建议改小一点。经测试125m足够开发测试使
用。
注意:Elasticsearch是使用java开发的,且本版本的es需要的jdk版本要是1.8及以上,所以安装
Elasticsearch之前保证JDK1.8+安装完毕,并正确的配置好JDK环境变量,否则启动Elasticsearch失败。
2.2 配置ElasticSearch-head
1. 在Chrome浏览器地址栏中输入:chrome://extensions/
2. 打开Chrome扩展程序的开发者模式
3. 将资料中的 ElasticSearch-head-Chrome插件.crx 拖入浏览器的插件页面:
4. 解压crx插件,通过加载已解压的扩展程序来加载
5. 最后即可安装成功
2.3 配置Kibana
1、Kibana说明
Kibana是ElasticSearch的数据可视化和实时分析的工具,利用Elasticsearch的聚合功能,生成各种图
表,如柱形图,线状图,饼图等。
https://www.elastic.co/cn/products/kibana
2、安装配置
2.1 解压即安装成功
2.2 进入安装目录下的config目录的kibana.yml文件
修改elasticsearch服务器的地址:
修改kibana配置支持中文:
4、运行访问
4.1 进入安装目录下的bin目录
4.2 双击运行,启动成功:
elasticsearch.url: "http://localhost:9200"
i18n.locale: "zh-CN"
4.3 发现kibana的监听端口是5601,我们访问:http://127.0.0.1:5601
2.4 IK分词器依赖支持
Lucene的IK分词器早在2012年已经没有维护了,现在我们要使用的是在其基础上维护升级的版本,并
且开发为Elasticsearch的集成插件了,与Elasticsearch一起维护升级,版本也保持一致。
GitHub仓库地址:https://github.com/medcl/elasticsearch-analysis-ik
下载插件:
1、安装插件
插件已经在资料中准备好了,解压之后,存放到D:\elasticsearch-6.8.0\plugins\目录中,即可安装成功
插件。
注意:解压的时候,如下文件必须在plugins目录的第一级目录下
重新启动ElasticSearch之后,看到如下日志代表安装成功
2、测试
IK分词器有两种分词模式:ik_max_word和ik_smart模式。
ik_max_word:会将文本做最细粒度的拆分
ik_smart:会做最粗粒度的拆分,智能拆分
最细粒度的拆分结果:
请求方式:POST
请求url:http://127.0.0.1:9200/_analyze
请求体:
{
"analyzer": "ik_smart",
"text": "南京市长江大桥"
} {
"tokens": [
{
"token": "南京市",
"start_offset": 0,
"end_offset": 3,
"type": "CN_WORD",
"position": 0
},
{
"token": "南京",
"start_offset": 0,
"end_offset": 2,
"type": "CN_WORD",
"position": 1
},
{
"token": "市长",
"start_offset": 2,
"end_offset": 4,
"type": "CN_WORD",
"position": 2
},
{
"token": "市",
"start_offset": 2,
"end_offset": 3,
"type": "CN_CHAR",
"position": 3
},
{
"token": "长江大桥",
"start_offset": 3,
"end_offset": 7,
"type": "CN_WORD",
"position": 4
},
{
"token": "长江",
"start_offset": 3,
智能拆分结果:
3、添加扩展词典和停用词典
停用词:有些词在文本中出现的频率非常高。但对本文的语义产生不了多大的影响。例如英文的a、
an、the、of等。或中文的”的、了、呢等”。这样的词称为停用词。停用词经常被过滤掉,不会被进行
索引。在检索的过程中,如果用户的查询词中含有停用词,系统会自动过滤掉。停用词可以加快索引的
速度,减少索引库文件的大小。
扩展词:就是不想让哪些词被分开,让他们分成一个词。比如上面的江大桥
南京市长江大桥
南京市,长江大桥
南京,市长,江大桥
江大桥拆分出来,
"end_offset": 5,
"type": "CN_WORD",
"position": 5
},
{
"token": "大桥",
"start_offset": 5,
"end_offset": 7,
"type": "CN_WORD",
"position": 6
}
]
} {
"tokens": [
{
"token": "南京市",
"start_offset": 0,
"end_offset": 3,
"type": "CN_WORD",
"position": 0
},
{
"token": "长江大桥",
"start_offset": 3,
"end_offset": 7,
"type": "CN_WORD",
"position": 1
}
]
}
自定义扩展词库
1. 进入到D:\elasticsearch-6.8.0\plugins\elasticsearch-analysis-ik-6.8.0\config目录下, 新增自定义
词典myext_dict.dic
输入 :江大桥
2. 将我们自定义的扩展词典文件,配置到IKAnalyzer.cfg.xml文件中
3. 然后重启:
4. 进行测试:
{
"tokens": [
{
"token": "南京市",
"start_offset": 0,
"end_offset": 3,
"type": "CN_WORD",
核心内容
Elasticsearch是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。
然而它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。在Elasticsearch中,你可以对
文档(而非成行成列的数据)进行索引、搜索、排序、过滤。Elasticsearch比传统关系型数据库如下:
详细说明:
"position": 0
},
{
"token": "市长",
"start_offset": 3,
"end_offset": 5,
"type": "CN_WORD",
"position": 1
},
{
"token": "江大桥",
"start_offset": 5,
"end_offset": 8,
"type": "CN_WORD",
"position": 2
}
]
}
索引库(indexes) <-------------> 数据库(Databases)
类型(type) <------------------> 数据表(Table)
文档(Document) <--------------> 行(Row)
字段(Field) <-----------------> 列(Columns)
映射(mappings) <--------------> DDL创建数据库表的语句
概念
说明
索引库
(indexes)
索引库包含一堆相关业务,结构相似的文档document数据,比如说建立一个
商品product索引库,里面可能就存放了所有的商品数据。
类型(type)
type是索引库中的一个逻辑数据分类,一个type下的document,都有相同的
field,类似于数据库中的表。比如商品type,里面存放了所有的商品
document数据。6.0版本以后一个index只能有1个type,6.0版本以前每个
index里可以是一个或多个type。7.0以后,没有type这个概念了
文档
(document)
文档是es中的存入索引库最小数据单元,一个document可以是一条客户数
据,一条商品数据,一条订单数据,通常用JSON数据结构表示。document存
在索引库下的type类型中。
字段(field)
Field是Elasticsearch的最小单位。一个document里面有多个field,每个field
就是一个数据字段
映射配置
(mappings)
对type文档结构的约束叫做 映射(mapping) ,用来定义document的每个字段
的约束(相当于有主键或外键约束,非空约束等)。如:字段的数据类型、是否
分词、是否索引、是否存储等特性。type是模拟mysql中的table概念。表是有
结构的,也就是表中每个字段都有约束信息;
三. ES功能使用
说明文档地址: https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
实际开发中,有几种方式操作Elasticsearch服务:
第一类:发送http请求(RESTful风格)操作:9200端口
使用Postman发送请求直接操作。
使用ElasticSearch-head-master图形化界面插件操作
使用Elastic官方数据可视化的平台Kibana进行操作
第二类:通过Java代码操作:9300端口
Elasticsearch提供的Java API 客户端进行操作。
关系型数据库
新增数据库(show databases;)
删除数据库
新增表,删除表,查询表(show tables;)
文档的增删改查,分页查询,排序...
3.1 索引库操作
Elasticsearch采用Rest风格API,因此其API就是一次http请求,你可以用任何工具发起http请求
1.创建索引库
发送请求:
响应结果:
"acknowledged" : true, 代表操作成功 "shards_acknowledged" : true, 代表分片操作成功 "index" :
"jeflee" 表示创建的索引库名称
注意:创建索引库的分片数默认5片,在7.0.0之后的ElasticSearch版本中,默认分片数变为1片;
2.查看索引库
发送请求:
# 在kibana中,不用写地址和端口,/jeflee是简化写法,真实请求地址是:
http://127.0.0.1:9200/jeflee
# 请求方法:PUT
PUT /jeflee
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "jeflee"
} #
请求方法GET
GET /jeflee
响应结果:**
响应内容解释:
{
"jeflee" : {
"aliases" : { },
"mappings" : { },
"settings" : {
"index" : {
"creation_date" : "1573610302775",
"number_of_shards" : "5",
"number_of_replicas" : "1",
"uuid" : "6Ffe20CIT76KchAcvqE6NA",
"version" : {
"created" : "6080099"
},
"provided_name" : "jeflee"
}
}
}
} {
"jeflee【索引库名】" : {
"aliases【别名】" : { },
"mappings【映射】" : { },
"settings【索引库设置】" : {
"index【索引】" : {
"creation_date【创建时间】" : "1573610302775",
"number_of_shards【索引库分片数】" : "5",
"number_of_replicas【索引库副本数】" : "1",
"uuid【唯一标识】" : "6Ffe20CIT76KchAcvqE6NA",
"version【版本】" : {
"created" : "6080099"
},
"provided_name【索引库名称】" : "jeflee"
}
}
}
}
3.删除索引库
发送请求:
响应结果
3.2 类型(type)及映射(mapping)操作
有了 索引库 ,等于有了数据库中的 database 。接下来就需要索引库中的 类型 了,也就是数据库中的
表 。创建数据库表需要设置字段约束,索引库也一样,在创建索引库的类型时,需要知道这个类型下
有哪些字段,每个字段有哪些约束信息,这就叫做 映射(mapping)
1.配置映射
给jeflee这个索引库添加了一个名为 goods 的类型,并且在类型中设置了4个字段:
title:商品标题
subtitle: 商品子标题
images:商品图片
price:商品价格
发送请求:
# 请求方法:DELETE
DELETE /jeflee
{
"acknowledged" : true
} P
UT /jeflee/goods/_mapping
{
"properties": {
"title":{
"type": "text",
"analyzer": "ik_max_word"
},
"subtitle":{
"type": "text",
"analyzer": "ik_max_word"
},
"images":{
"type": "keyword",
"index": false
},
"price":{
"type": "float",
"index": true
}
}
}
响应结果:
内容解释:
类型名称:就是前面将的type的概念,类似于数据库中的表 字段名:任意填写,下面指定许多属性,例
如:
type:类型,Elasticsearch中支持的数据类型非常丰富,说几个关键的:
1. String类型,又分两种:
text:可分词
keyword:不可分词,数据会作为完整字段进行匹配
2. Numerical:数值类型,分两类
基本数据类型:long、interger、short、byte、double、float、half_float
浮点数的高精度类型:scaled_float
3. Date:日期类型
4. Array:数组类型
5. Object:对象
index:是否索引,默认为true,也就是说你不进行任何配置,所有字段都会被索引。
true:字段会被索引,则可以用来进行搜索。默认值就是true
false:字段不会被索引,不能用来搜索
store:是否将数据进行独立存储,默认为false
原始的文本会存储在 _source 里面,默认情况下其他提取出来的字段都不是独立存储的,是
从 _source 里面提取出来的。当然你也可以独立的存储某个字段,只要设置store:true即
{
"acknowledged" : true
} P
UT /索引库名/_mapping/类型名称 或 索引库名/类型名称/_mapping
{
"properties": {
"字段名称":{
"type【类型】": "类型",
"index【是否索引】": true,
"store【是否存储】": true,
"analyzer【分析器】": "分词器"
} .
..
}
}
可,获取独立存储的字段要比从_source中解析快得多,但是也会占用更多的空间,所以要根
据实际业务需求来设置,默认为false。
analyzer:分词器,这里的 ik_max_word 即使用ik分词器
2.查看映射
发送请求:
响应结果:
3.一次创建索引库及配置映射(常用)
刚才的案例中,我们是把创建索引库和类型分开来做,其实也可以在创建索引库的同时,直接制定索引
库中的类型
发送请求:
# 请求方法:GET
GET /jeflee/goods/_mapping
{
"jeflee" : {
"mappings" : {
"goods" : {
"properties" : {
"images" : {
"type" : "keyword",
"index" : false
},
"price" : {
"type" : "float"
},
"subtitle" : {
"type" : "text",
"analyzer" : "ik_max_word"
},
"title" : {
"type" : "text",
"analyzer" : "ik_max_word"
}}}}}
} P
UT /jeflee1
{
"settings": {},
"mappings": {
"goods":{
"properties": {
"title":{
"type": "text",
"analyzer": "ik_max_word"
},
"subtitle":{
"type": "text",
响应结果:
请求内容解释:
3.3 文档操作
文档,即索引库中某个类型下的数据,会根据规则创建索引,将来用来搜索。可以类比做数据库中的每
一行数据。
1.新增文档
发送请求:
"analyzer": "ik_max_word"
},
"images":{
"type": "keyword",
"index": false
},
"price":{
"type": "float",
"index": true
}
}
}
}
} {
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "jeflee1"
} P
UT /{索引库名称}
{
"settings【设置】": {},
"mappings【映射】": {
"{类型名称}":{
"properties": {
"title":{
"type【类型】": "text",
"index【是否索引】": true,
"store【是否存储】": true,
"analyzer【分析器】": "ik_max_word"
} .
..
}
}
}
}
响应结果:
响应结果解析:
可以看到结果显示为: created ,是创建成功了。
另外,需要注意的是,在响应结果中有个 _id 字段,这个就是这条文档数据的 唯一标示 ,以后的增删改
查都依赖这个id作为唯一标示。可以看到id的值为:EwVLY24BL4R5dXuhZ--1,这里我们新增时没有指
定id,所以是ES帮我们随机生成的id。
2.查看文档
根据rest风格,新增是put,查询是get(post也可以用来做查询),不过查询一般都需要条件,这里我们
把刚刚生成数据的id带上。
发送请求:
POST /jeflee/goods
{
"title":"小米手机",
"images":"http://image.leyou.com/12479122.jpg",
"price":2699.00
} {
"_index" : "jeflee",
"_type" : "goods",
"_id" : "EwVLY24BL4R5dXuhZ--1",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
} {
"_index【索引库】" : "jeflee",
"_type【类型】" : "goods",
"_id【主键id】" : "EwVLY24BL4R5dXuhZ--1",
"_version【版本】" : 1,
"result【操作结果】" : "created",
"_shards【分片】" : {
"total【总数】" : 2,
"successful【成功】" : 1,
"failed【失败】" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
} G
ET /jeflee/goods/EwVLY24BL4R5dXuhZ--1
响应结果:
响应结果解析:
_source :源文档信息,所有的数据都在里面。
_id :这条文档的唯一标示
found:查询结果,返回true代表查到,false代表没有
3.自定义id新增文档
发送请求:
响应结果:
{
"_index" : "jeflee",
"_type" : "goods",
"_id" : "EwVLY24BL4R5dXuhZ--1",
"_version" : 1,
"
_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"title" : "小米手机",
"images" : "http://image.leyou.com/12479122.jpg",
"price" : 2699.0
}
} {
"_index【索引库】" : "jeflee",
"_type【类型】" : "goods",
"_id【主键id】" : "EwVLY24BL4R5dXuhZ--1",
"_version【版本】" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found【查询结果】" : true,
"_source【源文档信息】" : {
"title" : "小米手机",
"images" : "http://image.leyou.com/12479122.jpg",
"price" : 2699.0
}
} P
OST /jeflee/goods/1
{
"title":"小米手机",
"images":"http://image.leyou.com/12479122.jpg",
"price":2699.00
} {
"_index" : "jeflee",
"_type" : "goods",
"_id" : "1",
主键id变为指定的id
请求内容解析:
4.修改文档
新增时,主键不变则会将原有内容覆盖。
发送请求:
响应结果:
可以看到result结果是: updated ,显然是更新数据
5.删除文档
"
_version" : 1,
"result" : "created",
"
_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
} P
OST /jeflee/goods/{自定义注解id}
{
"title":"小米手机",
"images":"http://image.leyou.com/12479122.jpg",
"price":2699.00
} P
OST /jeflee/goods/1
{
"title":"超米手机",
"images":"http://image.leyou.com/12479122.jpg",
"price":3899.00
} {
"_index" : "jeflee",
"_type" : "goods",
"_id" : "1",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 1,
"_primary_term" : 1
}
1、删除一条
删除一个文档也不会立即从磁盘上移除,它只是被标记成已删除。Elasticsearch将会在你之后添加更多
索引的时候才会在后台进行删除内容的清理。
发送请求:
响应结果:
可以看到result结果是:deleted,数据被删除。如果删除不存在的问题,result:not_found
2、根据条件删除:
发送请求:
响应结果:
DELETE /jeflee/goods/1
{
"_index" : "jeflee",
"_type" : "goods",
"_id" : "1",
"_version" : 3,
"result" : "deleted",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 2,
"_primary_term" : 1
} P
OST /jeflee/_delete_by_query
{
"query":{
"match":{
"title":"小米"
}
}
} {
"took" : 58,
"timed_out" : false,
响应结果解析:
6.发送请求批量操作_bulk
Bulk 操作是将文档的增删改查一些列操作,通过一次请求全都做完。减少网络传输次数。相当于,将多
个新增、修改、删除的请求写到一次请求当中。
注意:bulk的请求体与其他的请求体稍有不同!
请求语法:
语法解析:
每行一定要以换行符(\n)结尾,包括最后一行
action/metadata 部分,指定做什么操作
action代表操作的动作,必须是如下的动作之一
"total" : 2,
"deleted" : 2,
"batches" : 1,
"version_conflicts" : 0,
"noops" : 0,
"retries" : {
"bulk" : 0,
"search" : 0
},
"throttled_millis" : 0,
"requests_per_second" : -1.0,
"throttled_until_millis" : 0,
"failures" : [ ]
} {
"took【耗时】" : 58,
"timed_out" : false,
"total【总数】" : 2,
"deleted【删除总数】" : 2,
"batches" : 1,
"version_conflicts" : 0,
"noops" : 0,
"retries" : {
"bulk" : 0,
"search" : 0
},
"throttled_millis" : 0,
"requests_per_second" : -1.0,
"throttled_until_millis" : 0,
"failures" : [ ]
} P
OST /jeflee/goods/_bulk
{ action: { metadata }}\n
{ request body }\n
{ action: { metadata }}\n
{ request body }\n
...
create:如果文档不存在,那么就创建
index:创建一个新的文档或者替换现有文档
update:部分更新文档
delete:删除一个文档,这种操作不带请求体
metadata,是文档的元数据,包括索引( _index ),类型( _type ),id( _id )...等
request body 请求体,正常的新增文档的请求体内容(注意,不要带换行符)
隔离:每个操作互不影响。操作失败的行会返回其失败信息。
实际用法:bulk请求一次不要太大,否则积压到内存中,性能会下降。所以,一次请求几千个操作、大
小控制在5M-15M之间正好。
发送请求:
注意:
请求体的内容不要换行
请注意 delete 动作不能有请求体
谨记最后一个换行符不要落下。
响应结果:
POST /jeflee/goods/_bulk
{"index":{"_index" : "jeflee","_type" : "goods"}}
{"title":"大米手机","images":"http://image.leyou.com/12479122.jpg","price":3288}
{"index":{"_index" : "jeflee","_type" : "goods"}}
{"title":"小米手机","images":"http://image.leyou.com/12479122.jpg","price":2699}
{"index":{"_index" : "jeflee","_type" : "goods"}}
{"title":"小米电视
4A","images":"http://image.leyou.com/12479122.jpg","price":4288}
{"index":{"_index" : "jeflee","_type" : "goods"}}
{"title": "华为手机","images": "http://image.leyou.com/12479122.jpg","price":
5288,"subtitle": "小米"}
{"index":{"_index" : "jeflee","_type" : "goods"}}
{"title":"apple手
机","images":"http://image.leyou.com/12479122.jpg","price":5899.00}
{
"took" : 41,
"errors" : false,
"items" : [
{
"index" : {
"_index" : "jeflee",
"_type" : "goods",
"_id" : "FFTEhm4BO0vjk-su75eC",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1,
"status" : 201
每个子请求都是独立执行,因此某个子请求的失败不会对其他子请求的成功与否造成影响。 如果其中任
何子请求失败,最顶层的 error 标志被设置为 true ,并且在相应的请求报告出错误明细。
status属性:代表响应状态码
四. 请求体查询
Elasticsearch提供了一个基于JSON的,在请求体内编写查询语句的查询方式。称之为请求体查询。
Elasticsearch 使用它以简单的 JSON接口来展现 Lucene 功能的绝大部分。这种查询语言相对于使用晦
涩难懂的查询字符串的方式,更灵活、更精确、易读和易调试。
这种查询还有一种称呼:Query DSL (Query Domain Specific Language),领域特定语言。
4.1.基本查询
1、查询所有(match_all)
发送请求:
请求内容解析:
这里的query代表一个查询对象,里面可以有不同的查询属性
查询类型:
例如: match_all(代表查询所有) , match , term , range 等等
查询条件:查询条件会根据类型的不同,写法也有差异
响应结果
}
} .
..
]
} P
OST /jeflee/_search
{
"query": {
"match_all": {}
}
} 请
求方法:POST
请求地址:http://127.0.0.1:9200/索引库名/_search
POST /{索引库}/_search
{
"query":{
"查询类型":{
"查询条件":"查询条件值"
}
}
}
响应结果解析:
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 3,
"max_score" : 1.0,
"hits" : [
{
"_index" : "jeflee",
"_type" : "goods",
"_id" : "ADWoZ24Bx8DA1HO-R9DD",
"_score" : 1.0,
"_source" : {
"title" : "小米电视4A",
"images" : "http://image.leyou.com/12479122.jpg",
"price" : 4288
}
},
{
"_index" : "jeflee",
"_type" : "goods",
"_id" : "_zWoZ24Bx8DA1HO-R8_D",
"_score" : 1.0,
"_source" : {
"title" : "小米手机",
"images" : "http://image.leyou.com/12479122.jpg",
"price" : 2699
}
},
{
"_index" : "jeflee",
"_type" : "goods",
"_id" : "_jWoZ24Bx8DA1HO-R8_D",
"_score" : 1.0,
"_source" : {
"title" : "大米手机",
"images" : "http://image.leyou.com/12479122.jpg",
"price" : 3288
}}]}}
{
"took【查询花费时间,单位毫秒】" : 1,
"timed_out【是否超时】" : false,
"_shards【分片信息】" : {
"total【总数】" : 5,
"successful【成功】" : 5,
"skipped【忽略】" : 0,
"failed【失败】" : 0
},
2、匹配查询(match)
match 类型查询,会把查询条件进行分词,然后进行查询,多个词条之间是or的关系
发送请求:
响应结果:
"hits【搜索命中结果】" : {
"total【命中总数】" : 3,
"max_score【所有查询结果中,文档的最高得分】" : 1.0,
"hits【命中结果集合】" : [
{
"_index【索引库】" : "jeflee",
"_type【类型】" : "goods",
"_id【主键】" : "ADWoZ24Bx8DA1HO-R9DD",
"_score【当前结果匹配得分】" : 1.0,
"_source【源文档信息】" : {
"title" : "小米电视4A",
"images" : "http://image.leyou.com/12479122.jpg",
"price" : 4288
}
}...}]}}
POST /jeflee/_search
{
"query": {
"match": {
"title": "小米手机"
}
}
} {
"took" : 5,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 3,
"max_score" : 0.5753642,
"hits" : [
{
"_index" : "jeflee",
"_type" : "goods",
"_id" : "_zWoZ24Bx8DA1HO-R8_D",
"_score" : 0.5753642,
"_source" : {
"title" : "小米手机",
"images" : "http://image.leyou.com/12479122.jpg",
"price" : 2699
}
在上面的案例中,不仅会查询到电视,而且与小米相关的都会查询到。某些情况下,我们需要更精确查
找,我们希望这个关系变成 and ,可以这样做:
发送请求:
本例中,只有同时包含 小米 和 手机 的词条才会被搜索到。
响应结果:
},
{
"
_index" : "jeflee",
"_type" : "goods",
"_id" : "ADWoZ24Bx8DA1HO-R9DD",
"_score" : 0.2876821,
"_source" : {
"title" : "小米电视4A",
"images" : "http://image.leyou.com/12479122.jpg",
"price" : 4288
}
},
{
"_index" : "jeflee",
"_type" : "goods",
"_id" : "_jWoZ24Bx8DA1HO-R8_D",
"_score" : 0.2876821,
"_source" : {
"title" : "大米手机",
"images" : "http://image.leyou.com/12479122.jpg",
"price" : 3288
}
}
]
}
} P
OST /jeflee/_search
{
"query": {
"match": {
"title": {
"query": "小米手机",
"operator": "and"
}
}
}
} {
"took" : 4,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
3、多字段匹配查询(multi_match)
multi_match 与 match 类似,不同的是它可以在多个字段中查询。
发送请求:
本例中,我们在title字段和subtitle字段中查询 小米 这个词
fields属性:设置查询的多个字段
响应结果:
"hits" : {
"total" : 1,
"max_score" : 0.5753642,
"hits" : [
{
"_index" : "jeflee",
"_type" : "goods",
"_id" : "_zWoZ24Bx8DA1HO-R8_D",
"_score" : 0.5753642,
"_source" : {
"title" : "小米手机",
"images" : "http://image.leyou.com/12479122.jpg",
"price" : 2699
}
}
]
}
} P
OST /jeflee/_search
{
"query": {
"multi_match": {
"query": "小米",
"fields": ["title","subtitle"]
}
}
} {
"took": 3,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 0.6099695,
"hits": [
{
"_index": "jeflee",
"_type": "goods",
4、关键词精确查询(term)
term查询,精确的关键词匹配查询,不对象查询条件进行分词
发送请求:
响应结果:
"_id": "qfHnLG4BWrjRrOzL8Ywa",
"
_score": 0.6099695,
"_source": {
"title": "小米电视4A",
"images": "http://image.leyou.com/12479122.jpg",
"price": 4288
}
},
{
"
_index": "jeflee",
"_type": "goods",
"_id": "qvHyLG4BWrjRrOzL9Yzn",
"_score": 0.2876821,
"_source": {
"title": "华为手机",
"images": "http://image.leyou.com/12479122.jpg",
"price": 5288,
"subtitle": "小米"
}
},
{
"_index": "jeflee",
"_type": "goods",
"_id": "qPHnLG4BWrjRrOzL3Yxl",
"_score": 0.2876821,
"_source": {
"title": "小米手机",
"images": "http://image.leyou.com/12479122.jpg",
"price": 2699
}
}
]
}
} P
OST /jeflee/_search
{
"query": {
"term": {
"title": {
"value": "小米"
}
}
}
} {
"took" : 0,
5、多关键词精确查询(terms)
terms 查询和 term 查询一样,但它允许你指定多值进行匹配。如果这个字段包含了指定值中的任何一
个值,那么这个文档满足条件,类似于mysql的in:
发送请求:
查询价格为2699或4288的商品
响应结果:
"timed_out" : false,
"
_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 2,
"max_score" : 0.6931472,
"hits" : [
{
"_index" : "jeflee",
"_type" : "goods",
"_id" : "CzXDZ24Bx8DA1HO-nNDZ",
"_score" : 0.6931472,
"_source" : {
"title" : "小米手机",
"images" : "http://image.leyou.com/12479122.jpg",
"price" : 2699
}
},
{
"_index" : "jeflee",
"_type" : "goods",
"_id" : "DDXDZ24Bx8DA1HO-nNDZ",
"_score" : 0.2876821,
"_source" : {
"title" : "小米电视4A",
"images" : "http://image.leyou.com/12479122.jpg",
"price" : 4288
}
}
]
}
} P
OST /jeflee/_search
{
"query": {
"terms": {
"price": [2699,4288]
}
}
}
4.2.结果过滤
默认情况下,elasticsearch在搜索的结果中,会把文档中保存在 _source 的所有字段都返回。如果我们
只想获取其中的部分字段,我们可以添加 _source 的过滤
1、指定字段
指定查询结果中,只显示title和price两个字段
发送请求:
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 2,
"max_score" : 0.6931472,
"hits" : [
{
"_index" : "jeflee",
"_type" : "goods",
"_id" : "CzXDZ24Bx8DA1HO-nNDZ",
"_score" : 0.6931472,
"_source" : {
"title" : "小米手机",
"images" : "http://image.leyou.com/12479122.jpg",
"price" : 2699
}
},
{
"_index" : "jeflee",
"_type" : "goods",
"_id" : "DDXDZ24Bx8DA1HO-nNDZ",
"_score" : 0.2876821,
"_source" : {
"title" : "小米电视4A",
"images" : "http://image.leyou.com/12479122.jpg",
"price" : 4288
}
}
]
}
}
2、过滤指定字段:includes和excludes
我们也可以通过:
includes:来指定想要显示的字段
excludes:来指定不想要显示的字段
二者都是可选的。
发送请求:
4.3.高级查询
1、布尔组合(bool)
POST /jeflee/_search
{
"_source": ["title","price"],
"query": {
"term": {
"price": 2699
}
}
} P
OST /jeflee/_search
{
"_source": {
"includes":["title","price"]
},
"query": {
"term": {
"price": 2699
}
}
} P
OST /jeflee/_search
{
"_source": {
"excludes": ["images"]
},
"query": {
"term": {
"price": 2699
}
}
}
bool 把各种其它查询通过 must (必须 )、 must_not (必须不)、 should (应该)的方式进行组合
发送请求:
响应结果:
2、范围查询(range)
range 查询找出那些落在指定区间内的数字或者时间。 range 查询允许以下字符:
post /jeflee/_search
{
"query":{
"bool":{
"must":
{ "match": { "title": "小米" }},
"must_not": { "match": { "title":
"电视" }},
"should":
{ "match": { "title": "手机" }}
}
}
} {
"took": 11,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.5753642,
"hits": [
{
"_index": "jeflee",
"_type": "goods",
"_id": "qPHnLG4BWrjRrOzL3Yxl",
"_score": 0.5753642,
"_source": {
"title": "小米手机",
"images": "http://image.leyou.com/12479122.jpg",
"price": 2699
}
}
]
}
}
操作符
说明
gt == (greater than)
大于>
gte == (greater than equal)
大于等于>=
lt == (less than)
小于<
lte == (less than equal)
小于等于<=
发送请求:
查询价格大于等于2699,且小于4000元的所有商品。
响应结果:
POST /jeflee/_search
{
"query": {
"range": {
"price": {"gte": 2699,"lt": 4000}
}
}
} {
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 2,
"max_score" : 1.0,
"hits" : [
{
"_index" : "jeflee",
"_type" : "goods",
"_id" : "CjXDZ24Bx8DA1HO-nNDZ",
"_score" : 1.0,
"_source" : {
"title" : "大米手机",
"images" : "http://image.leyou.com/12479122.jpg",
"price" : 3288
}
},
{
"_index" : "jeflee",
"_type" : "goods",
"_id" : "CzXDZ24Bx8DA1HO-nNDZ",
"_score" : 1.0,
"_source" : {
"title" : "小米手机",
"images" : "http://image.leyou.com/12479122.jpg",
3、模糊查询(fuzzy)
fuzzy自动将拼写错误的搜索文本,进行纠正,纠正以后去尝试匹配索引中的数据。它允许用户搜索词
条与实际词条出现偏差,但是偏差的编辑距离不得超过2:
发送请求:
如下查询,也能查询到apple手机
修改偏差值:
你搜索关键词的偏差,默认就是2,我们可以通过fuzziness修改。
4.4.查询排序
1、单字段排序
sort 可以让我们按照不同的字段进行排序,并且通过 order 指定排序的方式。desc降序,asc升序。
发送请求:
"price" : 2699
}
}
]
}
} P
OST /jeflee/_search
{
"query": {
"fuzzy": {
"title": "appla"
}
}
} P
OST /jeflee/_search
{
"query": {
"fuzzy": {
"title": {
"value": "applaa",
"fuzziness": 2
}
}
}
}
响应结果:
POST /jeflee/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"price": {"order": "desc"}
}
]
} {
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 5,
"max_score" : null,
"hits" : [
{
"_index" : "jeflee",
"_type" : "goods",
"_id" : "DjXDZ24Bx8DA1HO-nNDZ",
"_score" : null,
"_source" : {
"title" : "apple手机",
"images" : "http://image.leyou.com/12479122.jpg",
"price" : 5899.0
},
"sort" : [
5899.0
]
},
{
"_index" : "jeflee",
"_type" : "goods",
"_id" : "DTXDZ24Bx8DA1HO-nNDZ",
"_score" : null,
"_source" : {
"title" : "华为手机",
"images" : "http://image.leyou.com/12479122.jpg",
"price" : 5288,
"subtitle" : "小米"
},
"sort" : [
5288.0
]
},
2、多字段排序
假定我们想要结合使用 price和 _score(得分) 进行查询,并且匹配的结果首先按照价格排序,然后按
照相关性得分排序:
发送请求:
{
"
_index" : "jeflee",
"
_type" : "goods",
"_id" : "DDXDZ24Bx8DA1HO-nNDZ",
"_score" : null,
"_source" : {
"title" : "小米电视4A",
"images" : "http://image.leyou.com/12479122.jpg",
"price" : 4288
},
"sort" : [
4288.0
]
},
{
"_index" : "jeflee",
"_type" : "goods",
"_id" : "CjXDZ24Bx8DA1HO-nNDZ",
"_score" : null,
"_source" : {
"title" : "大米手机",
"images" : "http://image.leyou.com/12479122.jpg",
"price" : 3288
},
"sort" : [
3288.0
]
},
{
"_index" : "jeflee",
"_type" : "goods",
"_id" : "CzXDZ24Bx8DA1HO-nNDZ",
"_score" : null,
"_source" : {
"title" : "小米手机",
"images" : "http://image.leyou.com/12479122.jpg",
"price" : 2699
},
"sort" : [
2699.0
]
}
]
}
}
4.5.分页查询
发送请求:
size:每页显示多少条
from:当前页的起始索引,int from = (当前页 - 1) * 每页条数
POST /jeflee/_search
{
"query":{
"match_all":{}
},
"sort": [
{ "price": { "order": "desc" }},
{ "_score": { "order": "desc" }}
]
} P
OST /jeflee/_search
{
"query": {
"match_all": {}
},
"size": 2,
"from": 0
}
五. ElasticSearch Java API客户端
5.1 客户端开发环境搭建
Spring Boot集成Elasticsearch的时候,我们需要引入高阶客户端【elasticsearch-rest-high-levelclient】【elasticsearch-rest-client】和【elasticsearch】来操作Elasticsearch,在引入起步依赖的时
候,需要严格注意Elasticsearch和起步依赖的版本关系,否则在使用过程中会出很多问题
搭建步骤:
1. 创建SpringBoot的项目,勾选starter配置
2. 配置Maven依赖坐标
3. 将ElasticSearch的客户端对象,注入Spring的容器
4. 配置ElasticSearch,服务地址,端口号
5.2 创建索引索引库
1、新增索引库
配置过程:
1. 创建SpringBoot的项目,勾选starter配置
选spring Initializr
配置项目信息
勾选starter,开发者工具、Lombok、配置文件映射处理器
2. 配置Maven依赖坐标
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.8.0</version>
</dependency>
<!--elasticsearch的rest客户端-->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>6.8.0</version>
</dependency>
<!--elasticsearch的核心jar包-->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>6.8.0</version>
</dependency>
<!--elasticsearch的高级别rest客户端-->
<dependency>
<groupId>org.elasticsearch.client</groupId>
3. 将ElasticSearch的客户端对象,注入Spring的容器
4. 配置ElasticSearch,服务地址,端口号
@Configuration
@ConfigurationProperties(prefix = "elasticsearch")
@Component
public class ElasticSearchConfig {
private String host;
private Integer port;
//初始化RestHighLevelClient
@Bean(destroyMethod = "close")
public RestHighLevelClient client() {
//RestClient客户端构建器对象
RestClientBuilder restClientBuilder = RestClient.builder(new
HttpHost(host, port, "http"));
//操作es的高级rest客户端对象
RestHighLevelClient restHighLevelClient = new
RestHighLevelClient(restClientBuilder);
return restHighLevelClient;
} /
/getter ,setter,toString..省略
} #
es服务地址
elasticsearch.host=127.0.0.1
# es服务端口
elasticsearch.port=9200
# 配置日志级别,开启debug日志
logging.level.com.itheima=debug
目标:使用ElasticSearch的高阶客户端,编写Java代码,创建索引库
分析:
Java high level客户端的操作,是模仿我们通过发送请求调用RESTful接口调用的方式,本质还是请求获
取响应。
执行
发送请求中,传入请求对象的同时还设置了一个RequestOptions对象的静态成员变量DEFAULT。其含
义是,配置当前请求选项为默认值。
其中RequestOptions对象的作用是用来配置请求,主要配置项目有请求头,缓冲区大小(默认100M),
异常处理器(warningsHandler)。默认情况下,缓冲区大小100MB,请求头及异常处理器为空。
2、查看索引库
/**
* 索引库操作:
* 1.创建索引库
* 2.查询索引库
* 3.删除索引库
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo01IndexOperation {
//注入ES客户端对象
@Autowired
private RestHighLevelClient client;
/**
* 目标:创建索引库
* 1.创建请求对象
* 设置索引库name
* 2.客户端发送请求,获取响应对象
* 3.打印响应对象中的返回结果
* 4.关闭客户端,释放连接资源
*/
@Test
public void create() throws IOException {
//1.创建请求对象,创建索引的请求
CreateIndexRequest request = new CreateIndexRequest("heima3");
//2.客户端发送请求,获取响应对象
CreateIndexResponse response = client.indices().create(request,
RequestOptions.DEFAULT);
//3.打印响应对象中的返回结果
//返回index信息
System.out.println("index:"+response.index());
//acknowledged代表创建成功
System.out.println("acknowledged:"+response.isAcknowledged());
//4.关闭客户端,释放连接资源
client.close();
}
} /
**
* 查询索引
* 1.创建请求对象:查看索引库
执行
3、删除索引库
执行
5.3 配置映射
* 设置索引库name
* 2.客户端发送请求,获取响应对象
* 3.打印响应结果
* 4.关闭客户端,释放连接资源
*/
@Test
public void getIndex() throws IOException {
//1.创建请求对象:查看索引库
GetIndexRequest request = new GetIndexRequest("heima4");
//2.客户端发送请求,获取响应对象
GetIndexResponse response = client.indices().get(request,
RequestOptions.DEFAULT);
//3.打印响应结果
System.out.println("aliases: "+response.getAliases());
System.out.println("settings: "+response.getSettings());
System.out.println("mappings: "+response.getMappings());
//4.关闭客户端,释放连接资源
client.close();
} /
**
* 删除索引
* 1.创建请求对象:删除索引库
* 设置索引库name
* 2.客户端发送请求,获取响应对象
* 3.打印响应结果
* 4.关闭客户端,释放连接资源
*/
@Test
public void delete() throws IOException {
//1.创建请求对象:删除索引库
DeleteIndexRequest request = new DeleteIndexRequest("heima2");
//2.客户端发送请求,获取响应对象
AcknowledgedResponse response = client.indices().delete(request,
RequestOptions.DEFAULT);
//3.打印响应结果
System.out.println("acknowledged::"+response.isAcknowledged());
//4.关闭客户端,释放连接资源
client.close();
}
当配置Spring的ioc容器中的RestHighLevelClient对象的销毁执行方法之后,每次容器销毁对象时,必
然会执行close方法,所以我们在使用完对象,可以不用每次手动关闭客户端。
1、配置映射
RestHighLevelClient配置映射,与kibana略有区别。在客户端中配置映射,不支持设置类型type。不
设置type,并不代表没有,而是默认的type为 _doc 。
/**
* 映射操作:
* 1.配置映射,一共2种方式:
* 第一种:使用XContentBuilder,构建请求体
* 第二种:使用JSON字符串
* 2.查看映射配置
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo02MappingOperation {
//注入ES客户端对象
@Autowired
private RestHighLevelClient client;
/**
*目标:配置映射。第一种方式,使用XContentBuilder,构建请求体
* 1.创建请求对象:配置映射
* 设置索引库name
* 设置配置映射请求体
* 2.客户端发送请求,获取响应对象
* 3.打印响应结果
*/
@Test
public void putMappingMethodOne() throws IOException {
//1.创建请求对象:配置映射
PutMappingRequest request = new PutMappingRequest("heima4");
//构建请求体
XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();
jsonBuilder.startObject()
.startObject("properties")
.startObject("title")
.field("type","text").field("analyzer","ik_max_word")
.endObject()
.startObject("subtitle")
.field("type","text").field("analyzer","ik_max_word")
.endObject()
.startObject("category")
.field("type","keyword")
.endObject()
.startObject("brand")
.field("type","keyword")
.endObject()
.startObject("images")
执行
第二种方式:
执行
2、查看映射
.field("type","keyword").field("index",false)
.endObject()
.startObject("price")
.field("type","float")
.endObject()
.endObject()
.endObject();
//设置请求体,source("请求体json构建器对象");
request.source(jsonBuilder);
//2.客户端发送请求,获取响应对象
AcknowledgedResponse response = client.indices().putMapping(request,
RequestOptions.DEFAULT);
//3.打印响应结果
System.out.println("acknowledged::"+response.isAcknowledged());
}
} /
**
*目标:配置映射。第二种方式,使用JSON字符串
* 1.创建请求对象:配置映射
* 设置索引库name
* 设置配置映射请求体
* 2.客户端发送请求,获取响应对象
* 3.打印响应结果
*/
@Test
public void putMappingMethodTwo() throws IOException {
//1.创建请求对象:配置映射
PutMappingRequest request = new PutMappingRequest("heima5");
//设置请求体,source("请求体json字符串","请求体的数据类型");
request.source("{\"properties\":{\"title\":
{\"type\":\"text\",\"analyzer\":\"ik_max_word\"},\"subtitle\":
{\"type\":\"text\",\"analyzer\":\"ik_max_word\"},\"category\":
{\"type\":\"keyword\"},\"brand\":{\"type\":\"keyword\"},\"price\":
{\"type\":\"float\"},\"images\":{\"type\":\"keyword\",\"index\":false}}}",
XContentType.JSON);
//2.客户端发送请求,获取响应对象
AcknowledgedResponse response = client.indices().putMapping(request,
RequestOptions.DEFAULT);
//3.打印响应结果
System.out.println("acknowledged::"+response.isAcknowledged());
} /
**
* 查看映射
* 1.创建请求对象:查看映射
* 设置索引库name
* 2.客户端发送请求,获取响应对象
执行
5.4 文档操作
1、创建文档
创建实体:
创建操作代码:
* 3.打印响应结果
*/
@Test
public void getMapping() throws IOException {
//1.创建请求对象:查看映射
GetMappingsRequest request = new GetMappingsRequest();
//设置索引库name
request.indices("heima4");
//2.客户端发送请求,获取响应对象
GetMappingsResponse response = client.indices().getMapping(request,
RequestOptions.DEFAULT);
//3.打印响应结果
System.out.println("mappings::"+response.mappings());
System.out.println("Source::"+response.mappings().get("heima4").getSourceAsMap()
);
} p
ublic class Goods {
private Long id;//商品的唯一标识
private String title;//标题
private String subtitle;//子标题
private String category;//分类
private String brand;//品牌
private Double price;//价格
private String images;//图片地址
//...getter , setter , toString
} /
**
* 文档操作:
* 1.新增文档
* 2.根据id查询文档
* 3.修改文档
* 4.删除文档
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo03DocumentOperation {
//注入ES客户端对象
@Autowired
private RestHighLevelClient client;
/**
* 目标:新增文档
* 1.创建请求对象:新增文档
* 设置索引库name
执行
不设置主键ID
2、修改文档
主键id相同,修改数据
* 设置类型type
* 设置主键id,不设置随机生成
* 设置请求体
* 2.客户端发送请求,获取响应对象
* 3.打印响应结果
*/
@Test
public void createDoc() throws IOException {
//1.创建请求对象:新增文档
IndexRequest request = new IndexRequest();
//设置索引库名称
request.index("heima4");
//设置type类型
request.type("_doc");
//设置主键id
request.id("1");
//构造Goods对象
Goods good = new Goods(1l,"小米手机","小米","手机","小
米",19999.0,"http://image.leyou.com/12479122.jpg");
//对象转json
String goodJsonStr = new ObjectMapper().writeValueAsString(good);
//设置请求体.source("json请求字符串","请求体的数据类型");
request.source(goodJsonStr,XContentType.JSON);
//2.客户端发送请求,获取响应对象
IndexResponse response = client.index(request, RequestOptions.DEFAULT);
//3.打印响应结果
System.out.println("_index::"+response.getIndex());
System.out.println("_type::"+response.getType());
System.out.println("_id::"+response.getId());
System.out.println("result::"+response.getResult());
}
} /
**
* 修改文档
* 1.创建请求对象:修改文档
* 设置索引库name
* 设置类型type
* 设置主键id,必须设置
* 设置请求体
* 2.客户端发送请求,获取响应对象
* 3.打印响应结果
*/
@Test
public void updateDoc() throws IOException {
//1.创建请求对象:修改文档
UpdateRequest request = new UpdateRequest();
//设置索引库名称
request.index("heima4");
执行
3、根据id查询文档
执行
4、删除文档
//设置type类型
request.type("_doc");
//设置主键id
request.id("1");
//构造Goods对象
Goods good = new Goods(1l,"大米手机","炒米","手机","小
米",999.0,"http://image.leyou.com/12479122.jpg");
//对象转json
String goodJsonStr = new ObjectMapper().writeValueAsString(good);
//设置请求体.source("json请求字符串","请求体的数据类型");
request.doc(goodJsonStr,XContentType.JSON);
//2.客户端发送请求,获取响应对象
UpdateResponse response = client.update(request, RequestOptions.DEFAULT);
//3.打印响应结果
System.out.println("_index::"+response.getIndex());
System.out.println("_type::"+response.getType());
System.out.println("_id::"+response.getId());
System.out.println("result::"+response.getResult());
} /
**
* 根据id查询文档
* 1.创建请求对象:根据id查询文档
* 设置索引库name
* 设置类型type
* 设置主键id
* 2.客户端发送请求,获取响应对象
* 3.打印响应结果
*/
@Test
public void getDoc() throws IOException {
//1.创建请求对象:根据id查询文档
GetRequest request = new GetRequest();
//设置索引库name
request.index("heima4");
//设置类型type
request.type("_doc");
//设置主键id
request.id("1");
//2.客户端发送请求,获取响应对象
GetResponse response = client.get(request, RequestOptions.DEFAULT);
//3.打印响应结果
//3.打印响应结果
System.out.println("_index::"+response.getIndex());
System.out.println("_type::"+response.getType());
System.out.println("_id::"+response.getId());
System.out.println("_source::"+response.getSourceAsString());
}
执行
5、批量操作bulk
/**
* 删除文档
* 1.创建请求对象:删除文档
* 设置索引库name
* 设置类型type
* 设置主键id
* 2.客户端发送请求,获取响应对象
* 3.打印响应结果
*/
@Test
public void deleteDoc() throws IOException {
//1.创建请求对象:删除文档
DeleteRequest request = new DeleteRequest();
request.index("heima4");
request.id("1");
request.type("_doc");
//2.客户端发送请求,获取响应对象
DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
//3.打印响应结果
System.out.println("_index::"+response.getIndex());
System.out.println("_type::"+response.getType());
System.out.println("_id::"+response.getId());
System.out.println("_result::"+response.getResult());
} /
**
* 批量操作
* 1.批量新增
* 2.批量删除
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo04BulkOperation {
//注入ES客户端对象
@Autowired
private RestHighLevelClient client;
/**
* 目标:批量新增
* 1.创建请求对象:批量操作
* 2.批量操作中设置多个新增对象IndexRequest
* 3.客户端发送请求,获取响应对象
* 4.打印响应结果
*/
@Test
public void createDoc() throws IOException {
//1.创建请求对象:批量操作
BulkRequest request = new BulkRequest();
//2.批量操作中设置多个新增对象IndexRequest
IndexRequest addRequestOne = new
IndexRequest().id("1").type("_doc").index("heima3").source(XContentType.JSON,"id
",1L,"title","大米手机","category","手机","brand","小
米","price","2699.00","images","http://baidu.com");
request.add(addRequestOne);
IndexRequest addRequestTwo = new
IndexRequest().id("2").type("_doc").index("heima3").source(XContentType.JSON,"id
",2L,"title","大米手机","category","手机","brand","小
米","price","2699.00","images","http://baidu.com");
request.add(addRequestTwo);
//3.客户端发送请求,获取响应对象
BulkResponse response = client.bulk(request, RequestOptions.DEFAULT);
//4.打印响应结果
System.out.println("took::"+response.getTook());
System.out.println("Items::"+response.getItems());
} /
**
* 目标:批量删除
* 1.创建请求对象:批量删除
* 2.批量操作中设置多个删除对象DeleteRequest
* 3.客户端发送请求,获取响应对象
* 4.打印响应结果
*/
@Test
public void bulkDelete() throws IOException {
//1.创建请求对象:批量删除
BulkRequest request = new BulkRequest();
//2.批量操作中设置多个删除对象DeleteRequest
request.add(new DeleteRequest().id("1").type("_doc").index("heima3"));
request.add(new DeleteRequest().id("2").type("_doc").index("heima3"));
//3.客户端发送请求,获取响应对象
BulkResponse response = client.bulk(request, RequestOptions.DEFAULT);
//4.打印响应结果
System.out.println("took::"+response.getTook());
System.out.println("Items::"+response.getItems());
}
}
总结
理解Elasticsearch的作用
分布式全文检索引擎,全文检索引擎的核心倒排索引技术,先创建索引在进行搜索的一个过
程
理解分词器的作用:将查询的条件拆分成关键词,用关键词去索引表中匹配查询文档
能够安装Elasticsearch服务
能够使用Elasticsearch集成IK分词器
理解Elasticsearch的相关概念:索引库的概念,类型的概念(7.0之后消失了)、文档、字段、映射
能够使用Kibana操作Elasticsearch == mysql数据库
————————————————
版权声明:本文为CSDN博主「Hulake_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_53919192/article/details/127064325