Elasticsearch7.5 经验分享
1查询
ES是非关系型数据库,可将两张表设置成父子关联表,查询一张表可将另一张表的相关信息带出来,
更多表的查询只能先查第一张表,遍历第一次查询结果,循环里进行二次、三次...的查询,后面的查询用Multi并行多个表的查询。
分页展示的话,一次展示几条,仅仅几条进行关联查询也只是勉强够用,做Excel批量导出这种功能,是完全不可以的,太慢了。
做分页展示它总条数默认显示一万条,也可以设置显示真实条数,但当点击最后一页时,会报错,因为它是游标计算的,点击最后一页游标要跑到最后,后台撑不住太大的计算量,最多只查出几万条,一般采用百度的做法,不显示总页数,无点击最后一页按钮,而且每次查询排序可能不一样,因为是计算出来的。
聚合查询(按条件统计)很糟糕(慢)。
2.增、删、改
ES的增、删、改功能并不理想,速度比较慢。修改是线程不安全的。不适合做频繁改动的表。
3.总结
ES做单表查询是很好的速度非常快。做分页、关联、聚合都不合适。
Elasticsearch重要概念
cluster(集群)
集群中有多个节点,其中有一个为主节点,这个主节点是可以通过选举产生的,主从节点是对于集群内部来说的。
es是去中心化的,就是无中心节点,从外部来看es集群,逻辑上是个整体,与任何一个节点的通信和与整个es集群通信是等价的。
node(节点)
每个运行实例(服务器进程)为一个节点,每个节点可在同一机器上,也可在不同的机器上。
routing(路由)
找到此文档的主分片(文档的位置),默认情况下,这个值是由文档的id生成。
shards(分片)
es可以把一个完整的索引分成多个分片,把一个大的索引拆分成多个,分布到不同的节点上。构成分布式搜索。分片的数量只能在索引创建前指定,并且索引创建后不能更改。
primary shard(主分片)
每个文档都存储在一个分片中,当存一个文档的时候,会先存储在主分片中,然后复制到副本中。默认一个索引有5个主分片。可在制定分片的数量,当分片一旦建立,分片的数量则不能修改。
replica shard(副本分片)
每一个分片有零个或多个副本。副本主要是主分片的复制,其中有两个目的:
1、增加高可用性:当主分片失败的时候,可以从副本分片中选择一个作为主分片。
2、提高性能:当查询的时候可以到主分片或者副本分片中进行查询。
默认情况下,一个主分配有一个副本,但副本的数量可以在后面动态的配置增加。副本必须部署在不同的节点上,不能部署在和主分片相同的节点上。
template(模板)
索引可使用预定义的模板进行创建,这个模板称作Index templates。模板设置包括settings和mappings。
index(索引)
索引就是一个拥有相似特征的文档的集合。
一个索引由一个名字来标识(必须全部是小写字母的),对此索引中的文档进行搜索、更新和删除的时候,都要用到这个名字。在一个集群中,你能够创建任意多个索引。
type(类型)
通常,会为具有一组相同字段的文档定义一个类型。一个type下的document,都有相同的field。
一种type就像一类表。如用户表、员工表等。
注意:
- ES 5.x中一个index可以有多种type。
- ES 6.x中一个index只能有一种type。
- ES 7.x以后,将移除type这个概念。
mapping(映射)
定义每个字段的类型、字段所使用的分词器等。相当于关系型数据库中的表结构。一个映射可以事先被定义,或者在第一次存储文档的时候自动识别。
document(文档)
可被索引的基础信息单元,一个document可以是一条数据,通常用JSON数据结构表示,每个index下的type中,可以去存储多个document。一个document里面有多个field。
field(字段)
一个文档中包含零个或者多个字段,字段可以是一个简单的值(例如字符串、整数、日期),也可以是一个数组或对象的嵌套结构。字段类似于关系数据库中的表中的列。
source field(源)
默认情况下,你的原文档将被存储在_source这个字段中,当你查询的时候也是返回这个字段。
这可从搜索结果中访问原始的对象,这个对象返回一个精确的json字符串,这个对象不显示索引分析后的其他任何数据。
id
id是一个文件的唯一标识,如果在存库的时候没有提供id,系统会自动生成一个id,文档的index/type/id必须是唯一的。
recovery(恢复)
代表数据恢复或叫数据重新分布,es在有节点加入或退出时会根据机器的负载对索引分片进行重新分配,挂掉的节点重新启动时也会进行数据恢复。
River(数据源)
是其它存储方式(如:数据库)同步数据到es的一个方法。它是以插件方式存在的一个es服务,通过读取river中的数据并把它索引到es中。
gateway(持久化)
代表es索引的持久化存储方式,es默认是先把索引存放到内存中,当内存满了时再持久化到硬盘。当这个es集群关闭再重新启动时就会从gateway中读取索引数据。
es支持多种类型的gateway,有本地文件系统(默认),分布式文件系统,Hadoop的HDFS和amazon的s3云存储服务。
discovery.zen(找节点)
代表es的自动发现节点机制,es是一个基于p2p的系统,它先通过广播寻找存在的节点,再通过多播协议来进行节点之间的通信,同时也支持点对点的交互。
Transport(交互)
代表es内部节点或集群与客户端的交互方式,默认内部是使用tcp协议进行交互,同时它支持http协议(json格式)、thrift、servlet、memcached、zeroMQ等的传输协议(通过插件方式集成)。
term(索引词)
索引词,在elasticsearch中索引词(term)是一个能够被索引的精确值。foo,Foo Foo几个单词是不相同的索引词。索引词(term)是可以通过term查询进行准确的搜索。
text(文本)
是一段普通的非结构化文字,通常,文本会被分析称一个个的索引词,存储在elasticsearch的索引库中,为了让文本能够进行搜索,
文本字段需要事先进行分析;当对文本中的关键词进行查询的时候,搜索引擎应该根据搜索条件搜索出原文本。
analysis(分析)
将文本转换为索引词的过程,分析的结果依赖于分词器,比如: FOO BAR, Foo-Bar, foo bar这几个单词有可能会被分析成相同的索引词foo和bar,这些索引词存储在elasticsearch的索引库中。当用 FoO:bAR进行全文搜索的时候,搜索引擎根据匹配计算也能在索引库中搜索出之前的内容。这就是elasticsearch的搜索分析。
replica(副本)
shard的replica副本,replica可以在shard故障时提供备用服务。多个replica可提升搜索操作的吞吐量和性能。
segment(分段)
一个shard包含多个segment,每个segment都是倒排索引。查询时,每个shard会把所有segment结果汇总作为shard的结果返回。
Elasticsearch官网JavaAPI
SpringBoot的pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jackchen</groupId>
<artifactId>EsDemo4</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<elastic-version>7.5.0</elastic-version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.5.0</version>
<exclusions>
<exclusion>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
</exclusion>
<exclusion>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.5.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.5.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.4</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--反射用到-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- java编译插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
java客户端的重要组件
SearchRequest 、SearchSourceBuilder 、QueryBuilder 、SearchResponse 、SearchHit
public static void testRequest()throws Exception{
// 创建请求对象,设置查询多个文档库,也可指定单个文档库。
SearchRequest request = new SearchRequest("index01","index02","index03");
// 也可通过 indices 方法指定文档库中
request.indices("posts01","posts02", "posts03");
// 设置指定查询的路由分片
request.routing("routing");
// 指定优先去某个分片上去查询(默认的是随机先去某个分片)
request.preference("_local");
// 设置缓存
request.requestCache();
// 取出查询语句
request.toString();
}
public static void testSource()throws Exception{
//创建源
SearchSourceBuilder source= new SearchSourceBuilder();
// 第几页
source.from(0);
// 每页多少条数据(默认是10条)
source.size(100);
// 设置排序规则
source.sort(new ScoreSortBuilder().order(SortOrder.DESC));
source.sort(new FieldSortBuilder("id").order(SortOrder.ASC));
//获取的字段(列)和不需要获取的列
String[] includeFields = new String[]{"birthday","name"};
String[] excludeFields = new String[]{"age","address"};
source.fetchSource(includeFields,excludeFields);
// 设置超时时间
source.timeout(new TimeValue(60, TimeUnit.SECONDS));
source.highlighter();// 高亮
source.aggregation(AggregationBuilders.terms("by_company"));// 聚合
//分词查询
source.profile(true);
source.query();
}
public static void testBuilder()throws Exception{
//全匹配(查出全部)
MatchAllQueryBuilder matchAllQuery = QueryBuilders.matchAllQuery();
//匹配查询
MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("","").analyzer("");
//匹配文本查询
MatchPhraseQueryBuilder matchPhraseQuery = QueryBuilders.matchPhraseQuery("","");
//匹配文本前缀查询
MatchPhrasePrefixQueryBuilder matchPhrasePrefixQuery = QueryBuilders.matchPhrasePrefixQuery("","");
//判断莫子是否有值(String)
ExistsQueryBuilder existsQuery = QueryBuilders.existsQuery("");
//前缀查询
PrefixQueryBuilder prefixQuery = QueryBuilders.prefixQuery("","");
//精确查询
TermQueryBuilder termQuery = QueryBuilders.termQuery("","");
//范围查询
RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("birthday").from("2016-01-01 00:00:00");
QueryStringQueryBuilder queryBuilder009 = QueryBuilders.queryStringQuery("");
QueryBuilders.disMaxQuery();
HighlightBuilder highlightBuilder = new HighlightBuilder();
HighlightBuilder.Field highlightTitle =
new HighlightBuilder.Field("title");
highlightTitle.highlighterType("unified");
highlightBuilder.field(highlightTitle);
HighlightBuilder.Field highlightUser = new HighlightBuilder.Field("user");
highlightBuilder.field(highlightUser);
// 组合器
BoolQueryBuilder builder = QueryBuilders.boolQuery();
//过滤
builder.filter();
//且
builder.must();
//非
builder.mustNot();
//或
builder.should();
}
public static void testResponse()throws Exception {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost("127.0.0.1", 9200, "http")));
SearchRequest searchRequest = new SearchRequest("user");
// 同步
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
RestStatus status = response.status();
TimeValue took = response.getTook();
Boolean terminatedEarly = response.isTerminatedEarly();
boolean timedOut = response.isTimedOut();
int totalShards = response.getTotalShards();
int successfulShards = response.getSuccessfulShards();
int failedShards = response.getFailedShards();
for (ShardSearchFailure failure : response.getShardFailures()) {
// failures should be handled here
}
// 异步
ActionListener<SearchResponse> listener = new ActionListener<SearchResponse>() {
@Override
public void onResponse(SearchResponse searchResponse) {
}
@Override
public void onFailure(Exception e) {
}
};
client.searchAsync(searchRequest, RequestOptions.DEFAULT, listener);
}
public static void testHits()throws Exception {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost("127.0.0.1", 9200, "http")));
SearchRequest searchRequest = new SearchRequest("user");
// 同步
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
TotalHits totalHits = hits.getTotalHits();
//总数
long numHits = totalHits.value;
//
TotalHits.Relation relation = totalHits.relation;
float maxScore = hits.getMaxScore();
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
String index = hit.getIndex();
String id = hit.getId();
float score = hit.getScore();
String sourceAsString = hit.getSourceAsString();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String documentTitle = (String) sourceAsMap.get("title");
List<Object> users = (List<Object>) sourceAsMap.get("user");
Map<String, Object> innerObject =
(Map<String, Object>) sourceAsMap.get("innerObject");
}
// 高亮获取
for (SearchHit hit : response.getHits()) {
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
HighlightField highlight = highlightFields.get("title");
Text[] fragments = highlight.fragments();
String fragmentString = fragments[0].string();
}
// 获取聚合结果
Aggregations aggregations = response.getAggregations();
Terms byCompanyAggregation = aggregations.get("by_company");
Terms.Bucket elasticBucket = byCompanyAggregation.getBucketByKey("Elastic");
Avg averageAge = elasticBucket.getAggregations().get("average_age");
double avg = averageAge.getValue();
// 获取大量聚合结果
Map<String, Aggregation> aggregationMap = aggregations.getAsMap();
Terms companyAggregation = (Terms) aggregationMap.get("by_company");
List<Aggregation> aggregationList = aggregations.asList();
for (Aggregation agg : aggregations) {
String type = agg.getType();
if (type.equals(TermsAggregationBuilder.NAME)) {
Terms.Bucket elasticBucket2 = ((Terms) agg).getBucketByKey("Elastic");
long numberOfDocs = elasticBucket2.getDocCount();
}
}
}
CountRequest(统计查出数量)(快)
public static void test001()throws Exception{
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
new HttpHost("127.0.0.1", 9200, "http")));
//统计匹配数量(不查出表的内容,更快。)
CountRequest countRequest = new CountRequest("user");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("name", "小");
sourceBuilder.query(queryBuilder);
countRequest.source(sourceBuilder);
CountResponse response =client.count(countRequest, RequestOptions.DEFAULT);
long count = response.getCount();
RestStatus status = response.status();
Boolean terminatedEarly = response.isTerminatedEarly();
int totalShards = response.getTotalShards();
int skippedShards = response.getSkippedShards();
int successfulShards = response.getSuccessfulShards();
int failedShards = response.getFailedShards();
System.out.println("**************************count: "+count);
System.out.println("status: "+status);
System.out.println("terminatedEarly: "+terminatedEarly);
System.out.println("totalShards: "+totalShards);
System.out.println("skippedShards: "+skippedShards);
System.out.println("successfulShards: "+successfulShards);
System.out.println("failedShards: "+failedShards);
for (ShardSearchFailure failure : response.getShardFailures()) {
System.out.println("failure: "+failure);
}
client.close();
}
ES的增、删、改、批量操作
//单条增
public static void addDocment()throws Exception{
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("127.0.0.1", 9200, "http")));
//Map提供供文档源
Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("name", "小红");
jsonMap.put("sex", "女");
jsonMap.put("age", 22);
jsonMap.put("birthDay", new Date());
jsonMap.put("message", "测试");
IndexRequest indexRequest1 = new IndexRequest("user2", "doc", "5")
.source(jsonMap);
// 同步执行
IndexResponse indexResponse1 =client.index(indexRequest1,RequestOptions.DEFAULT);
client.close();
//XContentBuilder提供供文档源
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
builder.field("name", "South");
builder.timeField("birthDay", new Date());
builder.field("message", "第二个小demo");
}
builder.endObject();
IndexRequest indexRequest2 = new IndexRequest("user", "doc", "2")
.source(builder);
// 同步执行
IndexResponse indexResponse2 =client.index(indexRequest2,RequestOptions.DEFAULT);
String index = indexResponse1.getIndex();
String type = indexResponse1.getType();
String id = indexResponse1.getId();
long version = indexResponse1.getVersion();
RestStatus restStatus = indexResponse1.status();
DocWriteResponse.Result result = indexResponse1.getResult();
ReplicationResponse.ShardInfo shardInfo = indexResponse1.getShardInfo();
client.close();
}
//删
public void deleteTest()throws Exception{
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
new HttpHost("127.0.0.1", 9200, "http")));
DeleteRequest request = new DeleteRequest("posts","1");
DeleteResponse deleteResponse = client.delete(request, RequestOptions.DEFAULT);
}
//单个改
public static void updateDocment()throws Exception{
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("127.0.0.1", 9200, "http")));
Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("name", "JunSouth");
UpdateRequest updateRequest = new UpdateRequest("user","doc","6").doc(jsonMap);
UpdateResponse updateResponse =client.update(updateRequest,RequestOptions.DEFAULT);
String index = updateResponse.getIndex();
String type = updateResponse.getType();
String id = updateResponse.getId();
long version = updateResponse.getVersion();
System.out.println("index:"+index+" type:"+type+" id:"+id+" version:"+version);
if(updateResponse.getResult() == DocWriteResponse.Result.CREATED) {
System.out.println("文档已创建");
}else if(updateResponse.getResult() == DocWriteResponse.Result.UPDATED) {
System.out.println("文档已更新");
}else if(updateResponse.getResult() == DocWriteResponse.Result.DELETED) {
System.out.println("文档已删除");
}else if(updateResponse.getResult() == DocWriteResponse.Result.NOOP) {
System.out.println("文档不受更新的影响");
}
client.close();
}
//批量操作
public static void bulkDocment()throws Exception{
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("127.0.0.1", 9200, "http")));
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.add(new IndexRequest("user","doc","5")
.source(XContentType.JSON,"name", "test")); // 将第一个 IndexRequest 添加到批量请求中
bulkRequest.add(new IndexRequest("user","doc","6")
.source(XContentType.JSON,"name","test")); // 第二个
BulkResponse bulkResponse = client.bulk(bulkRequest,RequestOptions.DEFAULT);
boolean falgs = bulkResponse.hasFailures(); // true 表示至少有一个操作失败
System.out.println("falgs: "+falgs);
for (BulkItemResponse bulkItemResponse : bulkResponse) { // 遍历所有的操作结果
DocWriteResponse itemResponse = bulkItemResponse.getResponse(); // 获取操作结果的响应,可以是 IndexResponse,UpdateResponse or DeleteResponse,它们都可以惭怍是 DocWriteResponse 实例。
if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.INDEX || bulkItemResponse.getOpType() == DocWriteRequest.OpType.CREATE) {
IndexResponse indexResponse = (IndexResponse) itemResponse;
System.out.println("index 操作后的响应结果");
}else if(bulkItemResponse.getOpType() == DocWriteRequest.OpType.UPDATE) {
UpdateResponse updateResponse = (UpdateResponse) itemResponse;
System.out.println("update 操作后的响应结果");
}else if(bulkItemResponse.getOpType() == DocWriteRequest.OpType.DELETE) {
DeleteResponse deleteResponse = (DeleteResponse) itemResponse;
System.out.println("delete 操作后的响应结果");
}
}
for (BulkItemResponse bulkItemResponse : bulkResponse) {
if (bulkItemResponse.isFailed()) { // 检测给定的操作是否失败
BulkItemResponse.Failure failure = bulkItemResponse.getFailure();
System.out.println("获取失败信息: "+failure);
}
}
client.close();
}
IndexRequest、DeleteRequest、UpdateRequest、BulkRequest
IndexRequest indexRequest
设置路由值。
indexRequest.routing("routing");
设置parent值。
indexRequest.parent("parent");
等待主碎片可用的作为TimeValue的超时。
等待主碎片可用的作为String的超时。
indexRequest.timeout(TimeValue.timeValueSeconds(1));
indexRequest.timeout("1s");
刷新策略作为WriteRequest.RefreshPolicy实例提供。
刷新策略作为String提供。
indexRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);
indexRequest.setRefreshPolicy("wait_for");
设置版本。
indexRequest.version(2);
设置版本类型。
indexRequest.versionType(VersionType.EXTERNAL);
操作类型作为DocWriteRequest.OpType值提供。
作为String提供的操作类型:可以为create或update(默认)。
indexRequest.opType(DocWriteRequest.OpType.CREATE);
indexRequest.opType("create");
索引文档之前要执行的摄取管道的名称。
indexRequest.setPipeline("pipeline");
DeleteRequest deleteRequest
设置路由值。
deleteRequest.routing("routing");
设置parent值。
deleteRequest.parent("parent");
等待主碎片可用的作为TimeValue的超时。
等待主碎片可用的作为String的超时。
deleteRequest.timeout(TimeValue.timeValueMinutes(2));
deleteRequest.timeout("2m");
将刷新策略作为WriteRequest.RefreshPolicy实例。
将刷新策略作为String。
deleteRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);
deleteRequest.setRefreshPolicy("wait_for");
设置版本。
deleteRequest.version(2);
设置版本类型。
deleteRequest.versionType(VersionType.EXTERNAL);
UpdateRequest updateRequest
设置超时时间。
updateRequest.timeout(TimeValue.timeValueSeconds(1));
updateRequest.timeout("1s");
设置刷新策略。
updateRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);
updateRequest.setRefreshPolicy("wait_for");
设置冲突后重试次数。
updateRequest.retryOnConflict(3);
获取数据源,默认是开启的。
updateRequest.fetchSource(true);
包括特定字段。
String[] includes = new String[]{"updated", "r*"};
String[] excludes = Strings.EMPTY_ARRAY;
updateRequest.fetchSource(new FetchSourceContext(true, includes, excludes));
排除特定字段。
String[] includes = Strings.EMPTY_ARRAY;
String[] excludes = new String[]{"updated"};
updateRequest.fetchSource(new FetchSourceContext(true, includes, excludes));
指定版本。
updateRequest.version(2);
禁用 noop detection
updateRequest.scriptedUpsert(true);
设置如果更新的文档不存在,就必须要创建一个。
updateRequest.docAsUpsert(true);
BulkRequest bulkRequest
设置超时时间
bulkRequest.timeout(TimeValue.timeValueMinutes(2));
request.timeout("2m");
设置刷新策略
bulkRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);
bulkRequest.setRefreshPolicy("wait_for");
设置在批量操作前必须有几个分片处于激活状态。
bulkRequest.waitForActiveShards(2);
bulkRequest.waitForActiveShards(ActiveShardCount.ALL); // 全部分片都处于激活状态
bulkRequest.waitForActiveShards(ActiveShardCount.DEFAULT); // 默认
bulkRequest.waitForActiveShards(ActiveShardCount.ONE); // 一个
ES查询
//查询某索引下全部数据
public static void searchAll()throws Exception{
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost("127.0.0.1", 9200, "http")));
SearchRequest searchRequest = new SearchRequest("user"); // 设置搜索的 index 。
QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(queryBuilder); //设置搜索,可以是任何类型的 QueryBuilder.
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = client.search(searchRequest,RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
float maxScore = hits.getMaxScore();
for (SearchHit hit : hits.getHits()) {
System.out.println("hit: "+hit);
String sourceAsString = hit.getSourceAsString();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("name");
System.out.println("name: "+name);
}
client.close();
//匹配查询器
QueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("user", "kimchy")
.fuzziness(Fuzziness.AUTO)
.prefixLength(3)
.maxExpansions(10);
searchSourceBuilder.query(matchQueryBuilder);
//高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
HighlightBuilder.Field highlightTitle = new HighlightBuilder.Field("name"); // title 字段高亮
highlightTitle.highlighterType("unified"); // 配置高亮类型
highlightBuilder.field(highlightTitle); // 添加到 builder
HighlightBuilder.Field highlightUser = new HighlightBuilder.Field("user");
highlightBuilder.field(highlightUser);
searchSourceBuilder.highlighter(highlightBuilder);
}
//普通条件查询
public static void search01()throws Exception{
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost("127.0.0.1", 9200, "http")));
SearchRequest searchRequest = new SearchRequest("user"); // 设置搜索的 index 。
// 查询器
QueryBuilder queryBuilder01 = QueryBuilders.termQuery("name", "test"); //完全匹配
QueryBuilder queryBuilder02 =QueryBuilders.fuzzyQuery("name", "t"); //模糊查询
QueryBuilder queryBuilder03 =QueryBuilders.prefixQuery("name", "小"); //前缀查询
QueryBuilder queryBuilder04 =QueryBuilders.matchQuery("name", "小"); //匹配查询
WildcardQueryBuilder queryBuilder = QueryBuilders.wildcardQuery("name","*jack*");//搜索名字中含有jack文档(name中只要包含jack即可)
// 搜索器(排序、分页...)。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(queryBuilder04); // 设置搜索条件
searchSourceBuilder.from(0); // 起始 index
searchSourceBuilder.size(5); // 大小 size
// searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)); // 设置搜索的超时时间
// searchSourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC)); // 根据分数 _score 降序排列 (默认行为)
// searchSourceBuilder.sort(new FieldSortBuilder("_uid").order(SortOrder.ASC)); // 根据 id 降序排列
searchRequest.source(searchSourceBuilder); // 将 SearchSourceBuilder 添加到 SeachRequest 中。
SearchResponse searchResponse = client.search(searchRequest,RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
float maxScore = hits.getMaxScore();
for (SearchHit hit : hits.getHits()) {
String sourceAsString = hit.getSourceAsString();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("name");
System.out.println("hit: "+hit);
System.out.println("name: "+name);
}
client.close();
}
// 聚合查询
public static void search02()throws Exception{
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost("127.0.0.1", 9200, "http")));
SearchRequest searchRequest = new SearchRequest("user2");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 根据 sex 字段分组
TermsAggregationBuilder aggregation = AggregationBuilders.terms("my_sex")
.field("sex.keyword");
aggregation.subAggregation(AggregationBuilders.avg("avg_age")
.field("age")); // age(统计的字段)需是数值型
aggregation.subAggregation(AggregationBuilders.max("max_age")
.field("age"));
aggregation.subAggregation(AggregationBuilders.min("min_age")
.field("age"));
searchSourceBuilder.aggregation(aggregation);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
Aggregations aggregations = searchResponse.getAggregations();
Terms sexTerms = aggregations.get("my_sex");
//获取每组的信息
for (Terms.Bucket bucket : sexTerms.getBuckets()) {
System.out.println("分组的字段名: " + bucket.getKeyAsString());
System.out.println("每组数量: " + bucket.getDocCount());
}
//求平均
Terms.Bucket elasticBucket1 = sexTerms.getBucketByKey("女");
Avg averageAge1 = elasticBucket1.getAggregations().get("avg_age");
double avg1 = averageAge1.getValue();
System.out.println("女性平均年龄:"+avg1);
Terms.Bucket elasticBucket2 = sexTerms.getBucketByKey("男");
Avg averageAge2 = elasticBucket2.getAggregations().get("avg_age");
double avg2 = averageAge2.getValue();
System.out.println("男性平均年龄:"+avg2);
//求最大最小
Terms.Bucket elasticBucket3 = sexTerms.getBucketByKey("女");
Max maxAge3 = elasticBucket3.getAggregations().get("max_age");
double maxAge = maxAge3.getValue();
System.out.println("女性最大年龄:"+maxAge);
Terms.Bucket elasticBucket4 = sexTerms.getBucketByKey("女");
Min maxAge4 = elasticBucket4.getAggregations().get("min_age");
double minAge = maxAge4.getValue();
System.out.println("女性最大年龄:"+minAge);
client.close();
}
// 多查询
public static void multiSearch()throws Exception{
MultiSearchRequest multiSearchRequest = new MultiSearchRequest();
// 查两个张索引
SearchRequest firstSearchRequest = new SearchRequest("user");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchQuery("name", "大黑"));
firstSearchRequest.source(searchSourceBuilder);
multiSearchRequest.add(firstSearchRequest);
SearchRequest secondSearchRequest = new SearchRequest("car");
searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchQuery("weight", "3T"));
secondSearchRequest.source(searchSourceBuilder);
multiSearchRequest.add(secondSearchRequest);
// 取值1
MultiSearchResponse multiSearchResponse = client.msearch(multiSearchRequest,RequestOptions.DEFAULT);
MultiSearchResponse.Item firstResponse = multiSearchResponse.getResponses()[0];
SearchResponse firstSearchResponse = firstResponse.getResponse();
for (SearchHit hit : firstSearchResponse.getHits()) {
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("name");
}
MultiSearchResponse.Item secondResponse = response.getResponses()[1];
SearchResponse secondSearchResponse = secondResponse.getResponse();
for (SearchHit hit : secondSearchResponse.getHits()) {
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("weight");
}
// 取值2
for (MultiSearchResponse.Item item : multiSearchResponse.getResponses()) {
SearchResponse response = item.getResponse();
for (SearchHit hit : response.getHits()) {
String index=hit.getIndex();
//根据不同索引名作不同的处理。
if(index.equals("user")){
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("name");
}else if(index.equals("car")){
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("weight");
}
}
}
//滚动查询
public static void scrollSerach()throws Exception{
System.out.print("11111111111111111");
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost("127.0.0.1", 9200, "http")));
SearchRequest searchRequest = new SearchRequest("user"); // 设置搜索的 index 。
QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(queryBuilder); //设置搜索,可以是任何类型的 QueryBuilder.
//设置每次查询数量
searchSourceBuilder.size(3);
//设置滚动等待时间
final Scroll scroll = new Scroll(TimeValue.timeValueMinutes(1));
searchRequest.scroll(scroll);
searchRequest.source(searchSourceBuilder);
//第一次获取查询结果
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
String scrollId = searchResponse.getScrollId();
SearchHit[] searchHits = searchResponse.getHits().getHits();
for (SearchHit hit : searchHits) {
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
System.out.print("第一次获取查询结果,此处可做一些操作。");
String name = (String) sourceAsMap.get("name");
System.out.println("name: "+name);
}
//遍历剩余结果
while (searchHits != null && searchHits.length > 0) {
SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
scrollRequest.scroll(scroll);
searchResponse = client.scroll(scrollRequest, RequestOptions.DEFAULT);
scrollId = searchResponse.getScrollId();
searchHits = searchResponse.getHits().getHits();
for (SearchHit hit : searchHits) {
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
System.out.print("遍历剩余结果,此处可做一些操作。");
String name = (String) sourceAsMap.get("name");
System.out.println("name: "+name);
}
}
// 清除游标
ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
clearScrollRequest.addScrollId(scrollId);
ClearScrollResponse clearScrollResponse = client.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
boolean succeeded = clearScrollResponse.isSucceeded();
client.close();
}
}