Elasticsearch 分享
一、Elasticsearch 基础介绍
ElasticSearch 是分布式实时搜索、实时分析、实时存储引擎,简称(ES), 成立于2012年,是一家来自荷兰的、开源的大数据搜索、分析服务提供商,为企业提供实时搜索、数据分析服务,支持PB级的大数据。
基于Apache Lucene 开源搜索引擎,Lucene是目前公认的性能最好,最先进的,功能最全的搜索引擎。
Elasticsearch使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,通过简单RESTfulAPI来隐藏Lucene的复杂性,从而让全文搜索变得简单。 速度超出你的想像,从10亿的数据中查出一条只需要1-2秒
除了Lucene 和全文搜索,还有以下功能
分布式的实时文件存储,每个字段都被索引并可被搜索
分布式的实时分析搜索引擎
可以扩展到上百台服务器,处理PB级结构化或非结构化数据
而且,所有的这些功能被集成到一个服务里面,你的应用可以通过简单的RESTful API、各种语言的客户端甚至命令行与之交互。
为什么要用ElasticSearch?
全文检索开始使用SQL来写,使用like进行模糊查询。如果数据量比较大,用这种方法就会特别慢,可以使用索引使得速度相对提高,但还是达不到对大数据搜索的要求,所以要使用分布式的全文搜索引擎ElasticSearch。
1)、ES原理剖析
索引和搜索流程图
绿色代表索引过程,对要检索的内容进行索引构建一个索引库,
索引过程包括:确定的原始内容即要搜索的内容——>采集文档——>创建文档——>分析文档——>索引文档
红色代表搜索过程:从索引库中搜索内容,
搜索过程:用户通过搜索界面——>创建查询——>执行搜索,从索引库搜索——>渲染搜索结果
二、Elasticsearch基本概念:
索引(Index)
一个索引就是一个拥有几分相似特征的文档的集合。比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对对应于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。
类型(Type)6.0.0版本中弃用
类型,曾经是索引的逻辑类别/分区,允许您在同一索引中存储不同类型的文档,例如,一种类型用于用户,另一种类型用于博客帖子。
在一个索引中,你可以定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类/分区,其语义完全由你来定。
文档(Document)
一个文档是一个可被索引的基础信息单元。比如,你可以拥有某一个客户的文档,某一个产品的一个文档,当然,也可以拥有某个订单的一个文档。文档以JSON(Javascript Object Notation)格式来表示。文档必须被索引/赋予一个索引的type。
分片(Shards)
索引可能存储大量可能超过单个节点的硬件限制的数据。
如果我们的索引数据量很大,超过硬件存放单个文件的限制,就会影响查询请求的速度,Es引入了分片技术。一个分片本身就是一个完成的搜索引擎,文档存储在分片中,而分片会被分配到集群中的各个节点中,随着集群的扩大和缩小,ES会自动的将分片在节点之间进行迁移,以保证集群能保持一种平衡。分片有以下特点:
- ES的一个索引可以包含多个分片(shard);
- 每一个分片(shard)都是一个最小的工作单元,承载部分数据;
- 每个shard都是一个lucene实例,有完整的简历索引和处理请求的能力;
- 增减节点时,shard会自动在nodes中负载均衡;
- 一个文档只能完整的存放在一个shard上
- 一个索引中含有shard的数量,默认值为5,在索引创建后这个值是不能被更改的。
- 优点:水平分割和扩展我们存放的内容索引;分发和并行跨碎片操作提高性能/吞吐量;
- 每一个shard关联的副本分片(replica shard)的数量,默认值为1,这个设置在任何时候都可以修改。
副本(Replicasedit)
副本,是对分片的复制。目的是为了当分片/节点发生故障时提供高可用性,它允许您扩展搜索量/吞吐量,因为可以在所有副本上并行执行搜索。
一个分片可以有多个复制分片,也可以无复制分片。它的作用主要是防止分片故障,加速查询索引等功能,提供了高可用性。另外,复制分片是不和主分片在一起的,一个主分片在一台机器上,它的复制分片可能分布在其它N台机器上。在这里,我们可以把它理解为,一个分片的复制,就叫复制分片。每个分片会包含部分索引文件。文件由sgment组成 。
副本(replica shard)就是shard的冗余备份,它的主要作用:
1)、冗余备份,防止数据丢失;
2)、shard异常时负责容错和负载均衡;
注意:副本是乘法,越多越浪费,但也越保险。分片是除法,分片越多,单分片数据就越少也越分散。
集群
多台ES服务器的结合的统称叫ES集群,一个集群包含多台服务器,多个节点。
节点
一个节点是你集群中的一个服务器,作为集群的一部分,它存储你的数据,参与集群的索引和搜索功能。
节点种类
主节点:负责集群范围内轻量级的操作,例如创建或删除索引。跟踪那些节点是集群的一部分以及确定将哪些碎片分配给哪些节点
数据节点:包含已创建的索引文档的分片。数据节点处理及数据相关的操作。例如CRUD,搜索和聚合
调节节点:仅可路由请求,处理搜索缩减阶段并分配批量索引。本质上,仅协调节点充当智能负载平衡器
节点和分片如何工作?
一个集群至少有一个节点,而一个节点就是一个ElasticSearch进程,节点可以有多个默认索引,如果创建索引,索引将会由5个分片(primary shard,又称主分片)构成,每一个分片会有一个复制分片。
三、与传统的关系型数据库中的库、表、行、列等概念进行对比
关系型数据库 -> Databases(库) -> Tables(表) -> Rows(行) -> Columns(列)。
Elasticsearch -> Indeces(索引) -> Types(类型) -> Documents(文档) -> Fields(属性)。
RDBS | ES |
数据库(database) | 索引(index) |
表(table) | 类型(type)(ES6.0之后被废弃,es7中完全删除) |
表结构(schema) | 映射(mapping) |
行(row) | 文档(document) |
列(column) | 字段(field) |
索引(Schema) | 反向索引(Mapping) |
SQL | 查询DSL |
SELECT * FROM table | GET http://..... |
UPDATE table SET | PUT http://...... |
DELETE | DELETE http://...... |
(1)、关系型数据库中的数据库(database),等价与ES索引(index)
(2)、一个数据库下面有N张表(table),等价与1个索引Index下面有N多类型(Type)
备注:(ES6.0之后被废弃,es7中完全删除)
(3)、一个数据库表(table)下的数据有多行(row)多列(colum)组成,等价与一个Type由多文档(document)多字段(field)组成
(4)、在一个关系型数据库中,索引(Schema)定义了表,每个表的字段,还有表和字段的之间关系,与之对应,在ES中:反向索引(Mapping)定义索引下的Ttype的字段的处理规则,即如何建立、索引类型、是否保存原始索引JSON文档、是否压缩原始JSON文档、是否需要分词处理、如何进行分词处理等
(5)、在数据库中新增 INSERT、删除 DELTE、修改 UPDATE、查询 SEARCH操作等价于ES中的新增PUT/POST、删除DELETE、修改_update、查询GET
ES内置的RREST接口
搜索原理
(1)、客户端给DODE1发送请求,查询名字叫张三的数据
(2)、P1节点接收到请求,判断出当前数据的_ID对应的分片0,且分片P1中的数据对应复制分片R0,R1都有,就会将请求转发到R0进行处理
(3)、取出文档数据返回给P1,最终返回给前端
更新原理
(1)、客户端给NODE1发送更新请求
(2)、它转发请求到主分片所在的节点NODE3
(3)、NODE3从主分片检索出文档,修改_soure字段的JSON,然后在主分片上重建索引,如果有其他进程修改了文档,它以retry_on_conflict设置的次数重复步骤3,都未成功则放弃
(4)、如何NODE3更新文档成功,它同时转发文档的新版本到NODE1和NODE2上的复制节点以重建索引。当所有复制节点更新成功,NODE3返回成功给请求节点,然后返回用户端
创建/删除原理
(1)、客户端发送请求创建、删除请求
(2)、根据文档ID,它将转发请求到主分片所在节点NODE3
(3)、NODE3在主分片上执行请求,如果成功将转发请求到NODE1和NODE2的复制分片上,当所有复制分片成功,则NODE3返回成功信息给请求节点。在将信息返回给客户端
字段数据类型:
字符型:text(分词,不能用于排序、过滤查询、聚合查询)、keyWord
数字型:byte、short、integer、float、double
布尔型:boolean
日期型:date
二进制型:binary
对象类型:object
字段属性:
store:是否储存字段原始值(独立于_source字段)
index:是否参与索引
analyzer:指定分词器
boost:字段级别的分数加权
doc_values:是否对不分词建立正排序索引
fleld_data:是否对分词器建立正排序索引
properties:类型映射
ignore_above:超过指定字符的文本将忽略不被索引
include_in_all:是否包含该字段到_all字段中
index_optionss:倒排序索引的可选参数
norms:是否储存长度因子和分数加权(boost)
null_value:初始值
position_increment_gap:指定多字段的多个值之间的位置间隔
search_analyzer:指定搜索时分词器
similarity:指定评分策略
term_vector:指定返回哪些关于词条的统计信息
normalizer:标注化处理器
coerce:强制类型转换器
copy_to:创建自定义的_all属性
dynamic:动态映射策略
enabled:是否处理字段(正排序索引和倒排序索引)
eager_global_ordinals:是否立即加载全局序号
format:指定日期格式
ignore_malformed:忽略格式错误的字段
四、ES的特性:
速度快、易扩展、弹性、灵活、操作简单、多语言客户端、X-Pack、hadoop/spark强强联手、开箱即用。
- 分布式:横向扩展非常灵活
- 全文检索:基于lucene的强大的全文检索能力;
- 近实时搜索和分析:数据进入ES,可达到近实时搜索,还可进行聚合分析
- 高可用:容错机制,自动发现新的或失败的节点,重组和重新平衡数据
- 模式自由:ES的动态mapping机制可以自动检测数据的结构和类型,创建索引并使数据可搜索。
- RESTful API:JSON + HTTP
五、索引的应用
1、创建索引
PUT project_v1
{"settings": {"number_of_shards": 1,"number_of_replicas": 1},"mappings": {"properties": {"name_cn": {"type": "text"},"name_en": {"type": "keyword"},"project_type": {"type": "keyword"},"people_count": {"type": "integer"},"order_count": {"type": "long"},"date": {"type": "date","format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||yyyy-MM||epoch_millis"}}}
}
备注:text 用于索引全文值的字段,例如电子邮件正文或产品说明。它们通过分词器传递 ,以在被索引之前将字符串转换为单个术语的列表。分析过程允许Elasticsearch搜索单个单词中 每个完整的文本字段。文本字段不用于排序,很少用于聚合。 keyword 用于索引结构化内容的字段,例如电子邮件地址,主机名,状态代码,邮政编码或标签。它们通常用于过滤,排序,和聚合。keyword字段只能按其确切值进行搜索。 有时候一个字段同时拥有全文类型(text)和关键字类型(keyword)是有用的:一个用于全文搜索,另一个用于聚合和排序。
number_of_shards 是指索引要做多少个分片,只能在创建索引时指定,后期无法修改。
number_of_replicas 是指每个分片有多少个副本,后期可以动态修改
primary shard(主分片):每个文档都存储在一个分片中,当你存储一个文档的时候,系统会首先存储在主分片中,然后会复制到不同的副本中。默认情况下,一个索引有5个主分片。你可以在事先制定分片的数量,当分片一旦建立,分片的数量则不能修改。
replica shard(副本分片):每一个分片有零个或多个副本。副本主要是主分片的复制,可以 增加高可用性,提高性能。
默认情况下,一个主分配有一个副本,但副本的数量可以在后面动态的配置增加。
副本必须部署在不同的节点上,不能部署在和主分片相同的节点上。
2、新增索引数据
PUT /project_v1/_doc/1
{"name_en":"encourage","name_cn":"营销码","project_type":"营销","people_count":4,"order_count":1000000,"date":"2019-04-01"
}
3、查询索引数据
GET /project_v1/_search
{"query": {"match_all": {}}
}
4、匹配查询 match
GET /project_v1/_search
{"query": {"match": {"name_cn": "营销"}}
}
5、过滤查询 Filter
GET /project_v1/_search
{"query": {"bool": {"filter": {"range": {"date": {"gte": "2020-04-01"}}}}}
}
六、Elasticsearch 聚合查询
1.聚合的概念
官方对聚合有四个关键字:Metric(指标)、Bucketing(桶)、Pipeline(管道)、Matrix(矩阵),在查询请求体中以aggregations语法来定义聚合分析,也可简写成aggs
Metric(指标):指标分析类型,如计算最大值、最小值、平均值等(对桶内的文档进行聚合分析的操作)
Bucket(桶):分桶类型,类似sql中的group by语法(满足特定条件的文档的集合)
Pipeline(管道):管道分析类型,基于上一级的聚合分析结果进行再分析
Matrix(矩阵):矩阵分析类型(聚合是一种面向数值型的聚合,用于计算一组文档字段中的统计信息)
2.Metric(指标)聚合
Metric聚合分析分为单值分析和多值分析两类
1、单值分析,只输出一个分析结果
关键字有min, max,avg,sum,cardinality
2、多值分析,输出多个分析结果
关键字有stats,extended_stats,percentile_rank,top hits
1)、min, max,avg, sum
GET /project_v1/_search
{"size": 0,"aggs": {"min_people_count": {"min": {"field": "people_count"}},"max_order_count":{"max": {"field": "order_count"}},"avg_order_count":{"avg": {"field": "order_count"}},"sum_order_count":{"sum": {"field": "order_count"}}}
}
2)、cardinality
cardinality 关键字: 求唯一值,即不重复的字段有多少(相当于sql中的distinct)
GET /project_v1/_search
{"size": 0,"aggs": {"cardinality_project_type": {"cardinality": {"field": "project_type"}}}
}
3)、stats
统计信息,请求后会直接显示各种聚合结果(count,min,max,avg,sum)
GET /project_v1/_search
{"size": 0,"aggs": {"stats_order_count": {"stats": {"field": "order_count"}}}
}
4)、extended_stats
扩展的统计信息,比stats返回更多的统计信息
GET /project_v1/_search
{"size": 0,"aggs": {"extended_stats_order_count": {"extended_stats": {"field": "order_count"}}}
}
3.Bucket(桶)聚合
Bucket可以理解为一个桶,它会遍历文档中的内容,凡是符合某一要求的就放在一个桶中,分桶相当于sql中的group by
关键字有Terms Aggregation,Filter Aggregation,Histogram Aggregation,Date Aggregation
1、Terms Aggregation
根据某一项的每个唯一的值来聚合
GET /project_v1/_search
{"size": 0,"aggs": {"terms_project_type": {"terms": {"field": "project_type","size": 3}}}
}
2、Filter Aggregation
指具体的域和具体的值,可以在Terms Aggregation 的基础上进行了过滤,只对特定的值进行了聚合
#查营销类型的总订单数
GET /project_v1/_search
{"size": 0,"aggs": {"filter_project_type": {"filter": {"term": {"project_type": "营销"}},"aggs": {"sum_order_count": {"sum": {"field": "order_count"}}}}}
}
3、Histogram Aggregation
Histogram与Terms聚合类似,都是数据分组,区别是Terms是按照Field的值分组,而Histogram可以按照指定的间隔对Field进行分组
#项目规模
GET /project_v1/_search
{"size": 0,"aggs": {"project_scale": {"histogram": {"field": "people_count","interval": 1}}}
}
4、Date Aggregation
针对时间格式数据的直方图聚合,基本特性与Histogram Aggregation一致
#项目发展史
GET /project_v1/_search
{"size": 0,"aggs": {"date_by_day": {"date_histogram": {"field": "date","calendar_interval": "day","min_doc_count": 1}}}
}
4.Pipeline(管道)聚合
管道的概念:支持对聚合分析的结果,再次进行聚合分析
#查项目类型最少人数的项目类型
GET /project_v1/_search
{"size":0,"aggs":{"project_type":{"terms": {"field": "project_type","size": 3},"aggs":{"sum_people_count":{"sum": {"field": "people_count"}}}},"min_people_count_by_project_type":{"min_bucket": {"buckets_path": "project_type>sum_people_count"}}}
}
5.总结
Metric(指标):分类并对一组文档进行sum、avg等数学运算
Bucketing(桶):桶聚合,常规的分类然后计算每个分类的文档数量
Pipeline(管道):对聚合的结果再次聚合
Matrix(矩阵):可在多个字段上计算,生成矩阵结果
七,通过SQL查询Elasticsearch
1.为什么用SQL查询
Elasticsearch 的官方查询语言是 Query DSL,既然是官方指定的,说明最吻合 ES 的强大功能,为ES做支撑。
其实,SQL 作为一个数据库查询语言,它语法简洁,书写方便而且大部分服务端程序员都清楚了解和熟知它的写法。但是作为一个 ES 新人来说,就算他已经是一位编程界的老江湖,但是如果他不熟悉 ES ,那么他如果要使用公司已经搭好的 ES 服务,他必须要先学习 Query DSL,学习成本也是一项影响技术开发进度的因素而且不稳定性高。但是如果 ES 查询支持 SQL的话,那么也许就算他是工作一两年的同学,他虽然不懂 ES的复杂概念,他也能很好的使用 ES 而且顺利的参加到开发的队伍中,毕竟SQL 都会写
2.Elasticsearch-SQL
Elasticsearch-SQL不属于 Elasticsearch 官方的,它是 NLPChina(中国自然语言处理开源组织)开源的一个 ES 插件,主要功能是通过 SQL 来查询 ES,其实它的底层是通过解释 SQL,将SQL 转换为 DSL 语法,再通过DSL 查询。
查询语法
SELECT fields from indexName/type WHERE conditions
表名 tableName 的地方现在改为了索引名 indexName,如果有索引Type ,则indexName/type
POST _sql?format=txt
{"query": "select * from project_index limit 10"
}
SQL翻译成DSL语句
POST _sql/translate
{"query": "select name_en,COUNT(*) from project_index GROUP BY name_en"
}
八、注意点
1.版本问题
es 5到7的版本变动很大,其中包括type的变动
- 5.x 支持多种type
- 6.x 只能有一种type
- 7.x 将去除type 没有类型的概念了
2.ES并不可靠
ES不是可靠的存储系统,不是数据库,它有丢数据的风险。ES不是实时系统,数据写入成功只是trans log成功(类似于mysql的bin log),写入成功后立刻查询查不到是正常的。因为数据此刻可能还在内存里而不是进入存储引擎里。
3.同步问题
在需要添加新数据与新字段的时候,如果elasticSearch进行搜索是可能需要重新修改格式。之前的数据需要重新同步,对数据的管理有很多困难。
九、SpringBoot集成Elasticsearch
1.引入依赖
<properties><!--告诉springboot我们处理的ES的版本--><elasticsearch.version>7.10.2</elasticsearch.version>
</properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency>
</dependencies>
2.yml配置es集群
spring:elasticsearch:rest:uris:- 192.168.53.112:9200- 192.168.53.113:9200- 192.168.53.114:9200
3.简单Test
3.1 创建索引以及分片设置
@Test
public void createIndex() throws Exception{//1 创建索引并设置分片//1.1 创建一个RestHightLevelClient对象,相当于和服务端建立连接。RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(//没有集群的话 此处可new 一个即可。new HttpHost("192.168.53.112",9200)new HttpHost("192.168.53.113",9200),new HttpHost("192.168.53.114",9200),));//1.2 使用client的索引管理的对象,indices()返回索引管理对象。IndicesClient indicesClient = client.indices();//两个参数//1.2.1 创建索引请求对象 参数:创建的索引库的名称CreateIndexRequest request = new CreateIndexRequest("hello").settings(Settings.builder().put("number_of_shards", 5).put("number_of_replicas", 1).build());//1.2.2 请求选项,使用默认值。配置请求头,主要用于认证。CreateIndexResponse response = indicesClient.create(request, RequestOptions.DEFAULT);//显示结果System.out.println(response.toString());}
3.2 创建索引库并设置mapping信息
@Test
public void createIndexAndMapping() throws Exception{RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(//没有集群的话 此处可new 一个即可。new HttpHost("192.168.53.112",9200)new HttpHost("192.168.53.113",9200),new HttpHost("192.168.53.114",9200),));//创建json数据XContentBuilder mappings = XContentFactory.jsonBuilder().startObject().startObject("properties").startObject("id").field("type","long").endObject().startObject("title").field("type","text").field("analyzer","ik_smart").field("store",true).endObject().endObject().endObject();//创建索引请求对象 参数:创建的索引库的名称,分片副片数量以及mapping信息CreateIndexRequest request = new CreateIndexRequest("hello1").settings(Settings.builder().put("number_of_shards", 5).put("number_of_replicas", 1).build()).mapping(mappings);//两个参数//1 创建索引请求对象 参数:创建的索引库的名称//2 请求选项,使用默认值。配置请求头,主要用于认证。CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);//显示结果System.out.println(response.toString());}
}
3.3删除索引库
@Test
public void deleteIndex() throws Exception{RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(//没有集群的话 此处可new 一个即可。new HttpHost("192.168.53.112",9200)new HttpHost("192.168.53.113",9200),new HttpHost("192.168.53.114",9200),));//删除索引库AcknowledgedResponse response = client.indices().delete(new DeleteIndexRequest("hello"), RequestOptions.DEFAULT);//显示结果System.out.println(response.toString());}
3.4 添加索引库字段信息
@Test
public void putIndex() throws Exception{RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(//没有集群的话 此处可new 一个即可。new HttpHost("192.168.53.112",9200)new HttpHost("192.168.53.113",9200),new HttpHost("192.168.53.114",9200),));String mappings = "{\n" +"\t\t\t\"properties\":{\n" +"\t\t\t\t\"id\":{\n" +"\t\t\t\t\t\"type\" : \"long\"\n" +"\t\t\t\t},\n" +"\t\t\t\t\"title\" :{\n" +"\t\t\t\t\t\"type\" : \"text\",\n" +"\t\t\t\t\t\"analyzer\" : \"ik_smart\",\n" +"\t\t\t\t\t\"store\" : true\n" +"\t\t\t\t},\n" +"\t\t\t\t\" content\" :{\n" +"\t\t\t\t\t\"type\" : \"text\",\n" +"\t\t\t\t\t\"analyzer\" : \"ik_smart\",\n" +"\t\t\t\t\t\"store\" :true\n" +"\t\t\t\t}\n" +"\t\t\t}\n" +"\t\t}";//将字符串以json形式发送PutMappingRequest request = new PutMappingRequest("hello1").source(mappings, XContentType.JSON);//修改索引库AcknowledgedResponse response = client.indices().putMapping(request, RequestOptions.DEFAULT);//显示结果System.out.println(response.toString());
}
十、Elasticsearch文档管理
0.抽取ES连接对象的公共方法
//原生客户端类,即ESjava客户端。
private RestHighLevelClient client;
public void init(){//1.1 创建一个RestHightLevelClient对象,相当于和服务端建立连接。client = new RestHighLevelClient(RestClient.builder(//没有集群的话 此处可new 一个即可。new HttpHost("192.168.53.112",9200)new HttpHost("192.168.53.113",9200),new HttpHost("192.168.53.114",9200),));
}
1.添加文档
使用RestHightLevelClient对象。
使用client对象的index方法添加文档
创建IndexRequest对象,其中包含了索引库名称、文档id、文档的内容
{“id”:“1”,“title”:“测试文档1”,“content”:“测试文档中的内容”}
public void addDocument() throws Exception{String document = "{\"id\":1, \"title\":\"这是测试文章\", \"content\":\"xxxxx\"}";//创建IndexRequest对象,其中包含索引库名称,文档id,文档内容IndexRequest request = new IndexRequest().index("hello1").id("1").source(document, XContentType.JSON);IndexResponse response = client.index(request, RequestOptions.DEFAULT);System.out.println(response.toString());}
2.更新文档
使用client对象的update方法。
需要UpdateRequest参数:
1.更新的索引
2.更新的文档的id
3.更新的文档内容
public void updateDocument() throws Exception{String document = "{\"id\":1, \"title\":\"这是测试文章更细的\", \"content\":\"new update\"}";//创建IndexRequest对象,其中包含索引库名称,文档id,文档内容UpdateRequest request = new UpdateRequest().index("hello1").id("1").doc(document, XContentType.JSON);UpdateResponse response = client.update(request, RequestOptions.DEFAULT);System.out.println(response.toString());}
3.删除文档
使用client的delete方法
需要DeleteRequest对象,需要两个参数
1.操作的索引
2.文档的id
public void deleteDocument() throws Exception{//创建IndexRequest对象,其中包含索引库名称,文档id,文档内容DeleteRequest request = new DeleteRequest("hello1", "1");DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);System.out.println(response.toString());}
4.根据id查询文档
使用client对象的get方法。
需要使用GetRequest对象,两个参数:
1.操作的索引
2.文档的id
public void getDocument() throws Exception{//创建IndexRequest对象,其中包含索引库名称,文档id,文档内容GetRequest request = new GetRequest("hello1", "1");GetResponse response = client.get(request, RequestOptions.DEFAULT);System.out.println(response.toString());}
5.批量查询文档
使用client对象的bulk方法。
BulkRequest对象,使用add方法,添加要批量处理的请求。
支持的处理:IndexRequest,DeleteRequest,UpdateRequest
public void bulkDocument() throws Exception{//json数据String jsonData = "[" +"{\"id\":3, \"title\":\"这是测试文章1\", \"content\":\"xxxxx\", \"comment\":\"备注信息\", \"mobile\":\"13344556677\"}\n" +"{\"id\":4, \"title\":\"这是一篇文章2\", \"content\":\"xxxxx\", \"comment\":\"备注信息\", \"mobile\":\"13344556677\"}\n" +"{\"id\":5, \"title\":\"这是一篇文章3\", \"content\":\"xxxxx\", \"comment\":\"备注信息\", \"mobile\":\"13344556677\"}]";//转换成json格式字符串JSONArray jsonArray = JSONObject.parseArray(jsonData);//创建IndexRequest对象,其中包含索引库名称,文档id,文档内容BulkRequest request = new BulkRequest();jsonArray.stream().forEach(json -> {IndexRequest r = new IndexRequest().index("hello1").id(((JSONObject) json).getString("id")).source(((JSONObject) json).toJSONString(), XContentType.JSON);request.add(r);});BulkResponse response = client.bulk(request, RequestOptions.DEFAULT);System.out.println(response.toString());}
十一、ElasticsearchRestTemplate类与ElasticsearchRepository类
SpringData对ES的封装ElasticsearchRestTemplate类,可直接使用,此类在ElasticsearchRestTemplate基础上进行性一定程度的封装,使用起来更方便灵活,拓展性更强。
ElasticsearchRepository可以被继承操作ES,是SpringBoot对ES的高度封装,操作最为方便,但牺牲了灵活性。
索引库实体类
@Data
@Document(indexName = "blog_1", shards = 5, replicas = 1)
public class Blog {@Field(type = FieldType.Long, store = true)private Long id;//type = FieldType.Text 字段类型为text//analyzer = "ik_max_word" 分词器为"ik_max_word"//store = true 存储 => 是@Field(type = FieldType.Text, analyzer = "ik_max_word", store = true)private String title;@Field(type = FieldType.Text, analyzer = "ik_max_word", store = true)private String content;@Field(type = FieldType.Text, analyzer = "ik_max_word", store = true)private String comment;@Field(type = FieldType.Keyword, store = true)private String mobile;}
1、使用ElasticsearchRestTemplate类
a)、创建索引库
@Autowired
private ElasticsearchRestTemplate template;/*** 创建索引库*/public void createIndex(){//创建索引库template. indexOps(IndexCoordinates.of("mytest")).create();}
b)、创建索引库并实体类设置mapping
1)创建索引库
template.indexOps(IndexCoordinates.of(“mytest”)).create();
2)设置mapping信息
需要创建一个实体类,其中配置实体类和文档的映射关系,使用注解配置。
可以从Entity中生成mapping信息。
public void putMapping(){//创建索引库Document mapping = template.indexOps(IndexCoordinates.of("mytest")).createMapping(Blog.class);template.indexOps(IndexCoordinates.of("mytest")).putMapping(mapping);
}
c)、删除索引库
//删除索引库public void deleteIndex(){template.indexOps(IndexCoordinates.of("hello1")).delete();}
d)、索引库查询
public void maxQueryTest(){NativeSearchQuery builder = new NativeSearchQueryBuilder()//多字段查询 (高亮跟查询条件有关).withQuery(QueryBuilders.multiMatchQuery("8", "id","title"))//增加过滤条件, 可以设置多个.withFilter(QueryBuilders.boolQuery()//增加bool查询:should的term关键字查询.should(QueryBuilders.termQuery("title", "文章")).should(QueryBuilders.termQuery("content","xxx")))//增加过滤条件的关键字查询.withFilter(QueryBuilders.termQuery("mobile", "13344556677"))//分页设置.withPageable(PageRequest.of(0,5))//设置高亮.withHighlightBuilder(new HighlightBuilder()//高亮显示的字段.field("title")//高亮显示的字段.field("content")//高亮显示的前缀.preTags("<em>")//高亮显示的后缀.postTags("</em>"))//添加聚合查询.addAggregation(new TermsAggregationBuilder("mobile_group").field("mobile")).build();//基于Blog.class 类型返回的结果SearchHits<Blog> searchHits = template.search(builder, Blog.class);//从searchHits取相关数据long totalHits = searchHits.getTotalHits(); //取总记录数List<SearchHit<Blog>> list = searchHits.getSearchHits(); //取每条数据放入集合中System.out.println("总记录数为:" + totalHits);list.forEach(blogSearchHit -> {//取原生文档对象Blog blog = blogSearchHit.getContent();System.out.println(blog);//取高亮对象Map<String, List<String>> highlightFields = blogSearchHit.getHighlightFields();System.out.println(highlightFields);//取高亮对象 放到Blog里去 这样就将Blog和高亮结合输出了String title = highlightFields.get("title").get(0);//String content = highlightFields.get("content").get(0);blog.setTitle(title);//blog.setContent(content);System.out.println(blog);});//取聚合结果Aggregations aggregations = searchHits.getAggregations();System.out.println(aggregations.toString());}
2、使用ElasticsearchRepository类
a)、创建接口继承ElasticsearchRepository
public interface BlogRepository extends ElasticsearchRepository<Blog, Long> {/*** 定义一个方法查询:根据title查询es** 原因: ElasticsearchRepository会分析方法名,参数对应es中的field(这就是灵活之处)* @param title* @return java.util.List<com.yt.cubemall.search.model.Blog>*/List<Blog> findByTitle(String title);/*** 定义一个方法查询: 根据title,content查询es*/List<Blog> findByTitleAndContent(String title, String content);}
b)、使用BlogRepository接口
public class BlogRepositoryTest {@Autowiredprivate BlogRepository blogRepository;/*** 添加文档*/@Testpublic void addDocument(){Blog blog = new Blog();for (int i = 0; i < 10; i++) {blog.setId((long)i+1);blog.setTitle("测试spring集成es"+i+1);blog.setContent("sjihfapf"+i+1);blog.setComment("注释内容"+i+1);blog.setMobile("12345678901");blogRepository.save(blog);}}/*** 更新文档*/@Testpublic void updateDocument(){Optional<Blog> optional = blogRepository.findById(1l);if (optional.isPresent()){Blog blog = optional.get();blog.setTitle("hello update");blogRepository.save(blog);}}/*** 删除文档*/@Testpublic void deleteDocument() {blogRepository.deleteById(1l);}/*** 查询所有 文档*/@Testpublic void getDocument() {//根据id查找//Optional<Blog> optional = blogRepository.findById(1l);//Blog blog = optional.get();//System.out.println(blog);//查找全部//Iterable<Blog> all = blogRepository.findAll();//all.forEach(blog -> System.out.println(blog));//分页查找全部Iterable<Blog> all = blogRepository.findAll(PageRequest.of(1,10));all.forEach(blog -> System.out.println(blog));}/*** 自定义方法:根据title内容查询索引库* /@Testpublic void testFindByTitle(){List<Blog> blogList = blogRepository.findByTitle("测试");blogList.stream().forEach(System.out::println);}/*** 自定义方法:根据title,content内容查询索引库* /@Testpublic void testFindByTitleAndContent(){List<Blog> blogList = blogRepository.findByTitleAndContent("测试", "sjihfapf");blogList.stream().forEach(System.out::println);}
}}
相关文章:

Elasticsearch 分享
一、Elasticsearch 基础介绍 ElasticSearch 是分布式实时搜索、实时分析、实时存储引擎,简称(ES), 成立于2012年,是一家来自荷兰的、开源的大数据搜索、分析服务提供商,为企业提供实时搜索、数据分析服务,…...
cpu masks的初始化
在内核中,有几个位图变量是用作标识cpu数量和状态的,它们分别是: 变量名称用途循环所使用的宏cpu_possible_mask系统中有多少个可以运行的cpu核for_each_possible_cpucpu_present_mask系统中有多少个可处于运行状态的cpu核for_each_present_…...

【软件测试面试】银行项目测试面试题+答案(二)
目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 面试题࿱…...

视频极速切割无损工具免费版,亲测好用!
问题描述 最近想兼职做自媒体,最初想法是想把视频资源下载到本地,本地做一些剪辑和图文配音发布到自媒体app上,但是要把视频(腾讯视频qlv转mp4看我上一篇文章,也是免费版)切割成一小段的片段用手机剪太费劲了,网上好多…...
LightDB ecpg 支持 exec sql execute ... end-exec【24.1】【oracle 兼容】
LightDB 从24.1 版本开始支持 oracle pro*c 中执行匿名块的语法(之前可以通过do 语句执行匿名块): EXEC SQL EXECUTEanonymous block END-EXEC;因为匿名块不是SQL标准的一部分,所以此用法也不存在于SQL标准中。 示例 #include …...

菜品检测,基于YOLOV8
菜品检测,基于YOLOV8NANO,训练得到模型PT,然后转换成ONNX,OPENCV的DNN调用,支持C/PYTHON/ANDROID开发菜品检测,基于YOLOV8,能检测五种菜品,水豆腐、豆腐干、空心菜、豆芽菜、茄子...
前端面试练习24.3.5
webpack相关 项目使用webpack流程 进入一个初始化好的vue项目下载安装webpack相关依赖包/插件 npm install --save-dev webpack webpack-cli webpack-dev-server安装一些相关的loader,比如vue-loader,babel-loader,css-loader等创建webpack.config.js文…...
vim 编辑器
vim 编辑器是什么用途? vim 是一种强大而灵活的文本编辑器,广泛用于开发和系统管理任务。它可以在命令行界面中使用,并提供许多高级编辑功能和快捷键,使用户能够高效地编辑文本文件。 vim 编辑器适用于哪些语言? vim 编…...
docker安装MongoDB脚本
使用docker安装MongoDB只需要按以下步骤执行即可: 一、docker 运行 注意修改默认端口,防止被攻击: docker run -d --name mongo --restartalways -p 25066:28317 -v /usr/local/mongDb/configdb:/data/configdb -v /usr/local/mongDb/db:…...

资料下载-嵌入式 Linux 入门
学习的第一步是去下载资料。 1. 有哪些资料 所有资料分 4 类: ① 开发板配套资料(原理图、虚拟机的映像文件、烧写工具等),放在百度网盘 ② 录制视频过程中编写的文档、源码、图片,放在 GIT 仓库 ③ u-boot、linux 内核、buildroot 等比较大…...

错误票据 刷题笔记
开数组 读入数据 记录最小值和最大值 每次读入x; 让a[x]; 从最小值开始 向上扫 当扫到a[x]0时候为断号 扫到a[x]>1为重号; 该题的小技巧 未知长度的数据的读入方式 1.首先在头文件敲上 #include<sstream> #include<string> #include<…...

十堰网站建设公司华想科技具有10年的网站制作经验
2018年已经结束了。 华翔科技收到了很多客户的咨询,他们都有一个共同的问题:建一个网站需要多少钱? 但是,我们都会问:您有什么具体需求吗? 大多数人的答案是否定的,他们只是想打听一下价格。 十…...

站库分离技术--反向代理技术-雷池云WAF-给自己搭建一个安全点的网站
文章目录 概要整体架构流程技术名词解释技术细节ssh-ubuntu服务器docker-映射-链接-通信nginx反代mysql设置数据库新密码 小结我的mysql映射目录我的wordpress映射目录 成果展示 概要 新买了一个云服务器,想搭建一个站库分离的wordpress为主的网站,采用d…...

MySQL常见的索引类型介绍
我将为您详细讲解 MySQL 中常见的索引类型,以及它们的使用场景、特点、区别和优势。索引是提高数据库查询性能的关键工具,它可以加速数据检索速度,减少服务器的负担。在 MySQL 中,索引类型主要包括 B-Tree 索引、哈希索引、全文索…...

iOS——【自动引用计数】ARC规则及实现
1.3.3所有权修饰符 所有权修饰符一共有四种: __strong 修饰符__weak 修饰符__undafe_unretained 修饰符__autoreleasing 修饰符 __strong修饰符 _strong修饰符表示对对象的强引用,持有强引用的变量在超出其作用域的时候会被废弃,随着强引…...

智慧城市的前景:数字孪生技术在智慧城市中的应用前景
目录 一、引言 二、数字孪生技术及其在智慧城市中的应用概述 三、数字孪生技术在智慧城市中的应用前景 1、城市规划与仿真模拟 2、智能交通与出行服务 3、智慧环保与可持续发展 4、智慧公共服务与社会治理 5、智慧能源与绿色建筑 四、数字孪生技术在智慧城市中的挑战与…...

Everything:文件查找工具,一搜即得
名人说:东边日出西边雨,道是无晴却有晴。——刘禹锡 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 目录 一、软件介绍①Everything②核心功能③原理 二、下载安装①下载②安装 三、使用方法①文…...

【数据结构:树与堆】向上/下调整算法和复杂度的分析、堆排序以及topk问题
文章目录 1.树的概念1.1树的相关概念1.2树的表示 2.二叉树2.1概念2.2特殊二叉树2.3二叉树的存储 3.堆3.1堆的插入(向上调整)3.2堆的删除(向下调整)3.3堆的创建3.3.1使用向上调整3.3.2使用向下调整3.3.3两种建堆方式的比较 3.4堆排…...
vue3+element-plus el-input 自动获取焦点
虽然element有提供input的autofocus属性,但是当我们第二次进入页面就会发现autofocus已经不再生效,需要通过onMounted去触发input的focus解决这个问题。 1.先给el-input绑定一个ref:<el-input ref"inputRef" v-model"inp…...

简单了解TCP/IP四层模型
什么是计算机网络? 计算机网络我们可以理解为一个巨大的城市地图,我们想从A地前往B地,其中要走的路、要避开的问题都交给计算机网络解决,直到我们可以正常的到达目的地,那么我们会把其中的过程抽象成一个网络模型&…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
C语言中提供的第三方库之哈希表实现
一. 简介 前面一篇文章简单学习了C语言中第三方库(uthash库)提供对哈希表的操作,文章如下: C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...
Spring Boot + MyBatis 集成支付宝支付流程
Spring Boot MyBatis 集成支付宝支付流程 核心流程 商户系统生成订单调用支付宝创建预支付订单用户跳转支付宝完成支付支付宝异步通知支付结果商户处理支付结果更新订单状态支付宝同步跳转回商户页面 代码实现示例(电脑网站支付) 1. 添加依赖 <!…...
大数据驱动企业决策智能化的路径与实践
📝个人主页🌹:慌ZHANG-CSDN博客 🌹🌹期待您的关注 🌹🌹 一、引言:数据驱动的企业竞争力重构 在这个瞬息万变的商业时代,“快者胜”的竞争逻辑愈发明显。企业如何在复杂环…...
算法250609 高精度
加法 #include<stdio.h> #include<iostream> #include<string.h> #include<math.h> #include<algorithm> using namespace std; char input1[205]; char input2[205]; int main(){while(scanf("%s%s",input1,input2)!EOF){int a[205]…...