说明

High Level Client 是基于 Low Level Client 的。官方文档如下:

* https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/index.html
* https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html

依赖

<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>6.5.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency> <dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>6.5.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.5.0</version>
</dependency>

连接

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient; /**
* Java高级REST客户机在Java低级REST客户机之上工作。它的主要目标是公开特定于API的方法,这些方法接受请求对象作为参数并返回响应对象
* 可以同步或异步调用每个API。同步方法返回一个响应对象,而异步方法(其名称以async后缀结尾)需要一个侦听器参数
* 一旦接收到响应或错误,侦听器参数(在低层客户机管理的线程池上)将被通知。
* Java高级REST客户机依赖于Elasticsearch核心项目。它接受与TransportClient相同的请求参数,并返回相同的响应对象。
* Java高级REST客户机需要Java 1.8
* 客户机版本与开发客户机的Elasticsearch版本相同
* 6.0客户端能够与任意6.X节点通信,6.1客户端能够与6.1、6.2和任意6.X通信
*/
public class RestClientFactory { private RestClientFactory(){} private static class Inner{
private static final RestClientFactory instance = new RestClientFactory();
} public static RestClientFactory getInstance(){
return Inner.instance;
} public RestHighLevelClient getClient(){
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
//new HttpHost("localhost", 9201, "http"),
new HttpHost("localhost", 9200, "http")
)
);
return client;
} }

【JavaAPI与HTTP请求】

1. Index

HTTP请求

查看所有数据
GET twitter/t_doc/_search

---

# 添加数据[index]/[type]/[id]
PUT twitter/t_doc/
{
"user" : "kimchy",
"post_date" : "2018-12-24T11:32:00",
"message" : "trying out Elasticsearch"
}

结果:

{
"_index" : "twitter",
"_type" : "t_doc",
"_id" : "",
"_version" : ,
"result" : "created",
"_shards" : {
"total" : ,
"successful" : ,
"failed" :
},
"_seq_no" : ,
"_primary_term" :
}

Java 

    public static RestHighLevelClient index() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("user", "kimchy");
jsonMap.put("postDate", new Date());
jsonMap.put("message", "trying out Elasticsearch"); IndexRequest indexRequest = new IndexRequest("twitter", "t_doc", "1")
.source(jsonMap);
IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);
System.out.println(response.status().name());
return client;
}

结果:

CREATED

还有两种形式添加数据

    /**
* 方式二:XContentBuilder
* @return
* @throws IOException
*/
public static RestHighLevelClient index2() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
XContentBuilder builder = jsonBuilder();
builder.startObject();
{
builder.field("user", "kimchy");
builder.timeField("postDate", new Date());
builder.field("message", "trying out Elasticsearch");
}
builder.endObject();
IndexRequest indexRequest = new IndexRequest("twitter", "t_doc", "2")
.source(builder);
IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);
System.out.println(response.status().name());
return client;
} /**
* 方式三:Object key-pairs对象键
* 同步方法
* @return
* @throws IOException
*/
public static RestHighLevelClient index3() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
IndexRequest indexRequest = new IndexRequest("twitter", "t_doc", "3")
.source("user", "kimchy",
"postDate", new Date(),
"message", "trying out Elasticsearch");
IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT); // 同步方式
System.out.println(response.status().name());
return client;
}

还能异步创建&添加数据

    /**
* 异步方法
* @return
* @throws IOException
*/
public static RestHighLevelClient index4() throws IOException, InterruptedException {
ActionListener listener = new ActionListener<IndexResponse>() {
@Override
public void onResponse(IndexResponse indexResponse) {
System.out.println("Async:" + indexResponse.status().name());
if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {
// Todo
} else if (indexResponse.getResult() == DocWriteResponse.Result.UPDATED) {
// Todo
}
// 处理成功分片小于总分片的情况
ReplicationResponse.ShardInfo shardInfo = indexResponse.getShardInfo();
if (shardInfo.getTotal() != shardInfo.getSuccessful()) {
// Todo
}
} @Override
public void onFailure(Exception e) {
System.out.println("AsyncFailure:" + e.getMessage());
e.printStackTrace();
}
}; RestHighLevelClient client = RestClientFactory.getInstance().getClient();
IndexRequest indexRequest = new IndexRequest("twitter", "t_doc", "4")
.source("user", "kimchy",
"postDate", new Date(),
"message", "trying out Elasticsearch")
.routing("my_route"); // 指定路由 client.indexAsync(indexRequest, RequestOptions.DEFAULT, listener); // 异步方式
Thread.sleep(2000);
return client;
}

结果:

Async:CREATED

2. Get

 HTTP请求

# 获取数据
GET twitter/t_doc/
结果:
{
"_index" : "twitter",
"_type" : "t_doc",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : {
"postDate" : "2018-12-24T03:42:22.787Z",
"message" : "trying out Elasticsearch",
"user" : "kimchy"
}
}

可以指定routing

GET twitter/t_doc/?routing=my_route
结果:
{
"_index" : "twitter",
"_type" : "t_doc",
"_id" : "4",
"_version" : 1,
"_routing" : "my_route",
"found" : true,
"_source" : {
"user" : "kimchy",
"postDate" : "2018-12-24T06:08:45.178Z",
"message" : "trying out Elasticsearch"
}
}

可以只要数据信息_source

GET twitter/t_doc//_source?routing=my_route
结果:
{
"user" : "kimchy",
"postDate" : "2018-12-24T06:08:45.178Z",
"message" : "trying out Elasticsearch"
}

Java

    public static RestHighLevelClient getOne() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
GetRequest request = new GetRequest("twitter", "t_doc", "4").routing("my_route"); // 指定routing的数据,查询也要指定
try {
GetResponse response = client.get(request, RequestOptions.DEFAULT);
System.out.println(response.getSourceAsString());
} catch (ElasticsearchException e) {
// 处理找不到index的异常
if(e.status() == RestStatus.NOT_FOUND){
// TODO
}
}
return client;
}

结果:

{"user":"kimchy","postDate":"2018-12-24T06:08:45.178Z","message":"trying out Elasticsearch"}

异步获取,并且指定包含/排除的字段

    /**
* 查询-额外参数
* 异步获取
* @return
* @throws IOException
*/
public static RestHighLevelClient getOneOp() throws IOException, InterruptedException {
ActionListener<GetResponse> listener = new ActionListener<GetResponse>() {
@Override
public void onResponse(GetResponse documentFields) {
System.out.println(documentFields.getSourceAsString());
} @Override
public void onFailure(Exception e) {
System.out.println("Error:" + e.getMessage());
e.printStackTrace();
}
}; RestHighLevelClient client = RestClientFactory.getInstance().getClient();
GetRequest request = new GetRequest("twitter", "t_doc", "1");
String[] includes = new String[]{"message", "*Date"}; // 包含的字段
String[] excludes = Strings.EMPTY_ARRAY; // 排除的字段
FetchSourceContext fetchSourceContext =
new FetchSourceContext(true, includes, excludes);
request.fetchSourceContext(fetchSourceContext);
client.getAsync(request, RequestOptions.DEFAULT, listener);
Thread.sleep(2000);
return client;
}

结果:

{"postDate":"2018-12-24T03:42:22.787Z","message":"trying out Elasticsearch"}

到这里也应该知道,Rest API 对每个操作提供了同步/异步的方法。

3. Exist API

Java

    /**
* 检查是否存在
* @return
* @throws IOException
*/
public static RestHighLevelClient exist() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
GetRequest request = new GetRequest("twitter", "t_doc", "1");
request.storedFields("_none_"); // 禁用获取存储字段
request.fetchSourceContext(FetchSourceContext.DO_NOT_FETCH_SOURCE); // 禁用抓取_source
boolean exists = client.exists(request, RequestOptions.DEFAULT);
System.out.println(exists);
return client;
}

结果:

true

4.  Delete API

HTTP请求

DELETE twitter/t_doc/
结果:
{
"_index" : "twitter",
"_type" : "t_doc",
"_id" : "1",
"_version" : 2,
"result" : "deleted",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : ,
"_primary_term" :
}

Java

    /**
* 删除也可以异步、也可以捕获异常,成功删除的分片数量,版本冲突
* @return
* @throws IOException
*/
public static RestHighLevelClient deleteOne() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
DeleteRequest request = new DeleteRequest("twitter", "t_doc", "1");
DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
System.out.println(response.status().name());
// 处理找不到的情况
if (response.getResult() == DocWriteResponse.Result.NOT_FOUND) {
// TODO
}
return client;
}

结果:

NOT_FOUND

5. Delete By Query API

我这里有4条测试数据

{"user":"Tom","flag":"1"}
{"user":"foo","flag":"2"}
{"user":"bar","flag":"2"}
{"user":"baz","flag":"2"}

HTTP 请求

# 删除flag=的数据
POST twitter/_delete_by_query?conflicts=proceed
{
"query": {
"match": {
"flag": "2"
}
}
}
结果:
{
"took" : 183,
"timed_out" : false,
"total" : 3,
"deleted" : 3,
"batches" : 1,
"version_conflicts" : 0,
"noops" : 0,
"retries" : {
"bulk" : 0,
"search" : 0
},
"throttled_millis" : ,
"requests_per_second" : -1.0,
"throttled_until_millis" : ,
"failures" : [ ]
}

--扩展

# 清空索引全部数据
POST /[索引名]/_delete_by_query
{
"query": {
"match_all": {}
}
}

Java

    /**
* 根据查询条件删除
* @return
* @throws IOException
*/
public static RestHighLevelClient deleteByQuery() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
DeleteByQueryRequest request = new DeleteByQueryRequest("twitter");
request.setConflicts("proceed"); // 发生冲突即略过
request.setQuery(QueryBuilders.matchQuery("flag","2"));
BulkByScrollResponse bulkResponse = client.deleteByQuery(request, RequestOptions.DEFAULT);
TimeValue timeTaken = bulkResponse.getTook();
boolean timedOut = bulkResponse.isTimedOut();
long totalDocs = bulkResponse.getTotal();
long updatedDocs = bulkResponse.getUpdated();
long deletedDocs = bulkResponse.getDeleted();
long batches = bulkResponse.getBatches();
long noops = bulkResponse.getNoops();
long versionConflicts = bulkResponse.getVersionConflicts();
System.out.println("花费时间:" + timeTaken + ",是否超时:" + timedOut + ",总文档数:" + totalDocs + ",更新数:" +
updatedDocs + ",删除数:" + deletedDocs + ",批量次数:" + batches + ",跳过数:" + noops + ",冲突数:" + versionConflicts);
List<ScrollableHitSource.SearchFailure> searchFailures = bulkResponse.getSearchFailures(); // 搜索期间的故障
searchFailures.forEach(e -> {
System.err.println("Cause:" + e.getReason().getMessage() + "Index:" + e.getIndex() + ",NodeId:" + e.getNodeId() + ",ShardId:" + e.getShardId());
});
List<BulkItemResponse.Failure> bulkFailures = bulkResponse.getBulkFailures(); // 批量索引期间的故障
bulkFailures.forEach(e -> {
System.err.println("Cause:" + e.getCause().getMessage() + "Index:" + e.getIndex() + ",Type:" + e.getType() + ",Id:" + e.getId());
});
return client;
}

结果:

花费时间:97ms,是否超时:false,总文档数:3,更新数:0,删除数:3,批量次数:1,跳过数:0,冲突数:0

6. Update API

我有一条测试数据

{"user":"Tom","flag":"1"}

HTTP 请求

# 通过脚本更新
POST twitter/t_doc//_update
{
"script" : {
"source": "ctx._source.msg = params.msg",
"lang": "painless",
"params" : {
"msg" : "達に携帯で連絡取ろうと思ったら 電池が切れてて動かない"
}
}
}
# 通过文档更新
POST twitter/t_doc//_update
{
"doc" : {
"user" : "new_name"
}
}

upserts

# upserts(如果文档不存在,则把upsert里面的内容作为文档插入)
POST twitter/t_doc//_update
{
"script" : {
"source": "ctx._source.counter += params.count",
"lang": "painless",
"params" : {
"count" : 4
}
},
"upsert" : {
"counter" : 1
}
}
结果【创建新文档】:
{
"_index" : "twitter",
"_type" : "t_doc",
"_id" : "2",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : ,
"_primary_term" :
}

如果你再执行的话就是更新了

结果【更新文档】:
{
"_index" : "twitter",
"_type" : "t_doc",
"_id" : "2",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : ,
"_primary_term" :
}
查询:
GET twitter/t_doc/
结果:
{
"_index" : "twitter",
"_type" : "t_doc",
"_id" : "2",
"_version" : 2,
"found" : true,
"_source" : {
"counter" : 5
}
}

不用脚本而用文档更新

# 如果文档不存在,则将doc内容作为新文档插入(因为"doc_as_upsert" : true)
POST twitter/t_doc//_update
{
"doc" : {
"name" : "new_name"
},
"doc_as_upsert" : true
}
结果:
{
"_index" : "twitter",
"_type" : "t_doc",
"_id" : "3",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : ,
"_primary_term" :
}
查询:
GET twitter/t_doc/
结果:
{
"_index" : "twitter",
"_type" : "t_doc",
"_id" : "3",
"_version" : 1,
"found" : true,
"_source" : {
"name" : "new_name"
}
}

Java

    /**
* 通过脚本更新,可以添加字段
* @return
*/
public static RestHighLevelClient updateOne() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
UpdateRequest request = new UpdateRequest("twitter", "t_doc", "1"); Map<String, Object> parameters = singletonMap("msg", "達に携帯で連絡取ろうと思ったら 電池が切れてて動かない");
Script inline = new Script(ScriptType.INLINE, "painless",
"ctx._source.msg = params.msg", parameters);
request.script(inline); UpdateResponse update = client.update(request, RequestOptions.DEFAULT);
System.out.println(update.status().name());
return client;
}

输出:OK

GET twitter/t_doc/
结果:
{
"_index" : "twitter",
"_type" : "t_doc",
"_id" : "1",
"_version" : 4,
"found" : true,
"_source" : {
"user" : "Tom",
"flag" : "1",
"msg" : "達に携帯で連絡取ろうと思ったら 電池が切れてて動かない"
}
}

还可以通过XContentBuilder

    /**
* 通过XContentBuilder更新
* @return
* @throws IOException
*/
public static RestHighLevelClient updateOne2() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient(); XContentBuilder builder = jsonBuilder()
.startObject()
.startObject("animal")
.field("cat", "阿猫")
.field("dog", "阿狗")
.endObject()
.endObject();
UpdateRequest request = new UpdateRequest("twitter", "t_doc", "1").doc(builder); UpdateResponse update = client.update(request, RequestOptions.DEFAULT);
System.out.println(update.status().name());
return client;
}

输出:OK

GET twitter/t_doc/
结果:
{
"_index" : "twitter",
"_type" : "t_doc",
"_id" : "1",
"_version" : 5,
"found" : true,
"_source" : {
"user" : "Tom",
"flag" : "1",
"msg" : "達に携帯で連絡取ろうと思ったら 電池が切れてて動かない",
"animal" : {
"cat" : "阿猫",
"dog" : "阿狗"
}
}
}

还可以通过Map

    /**
* 通过jsonMap更新
* @return
* @throws IOException
*/
public static RestHighLevelClient updateOne3() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient(); Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("updateUser", "Jack Ma");
UpdateRequest request = new UpdateRequest("posts", "doc", "1").doc(jsonMap); UpdateResponse update = client.update(request, RequestOptions.DEFAULT);
System.out.println(update.status().name());
return client;
}

输出:OK

GET twitter/t_doc/
结果:
{
"_index" : "twitter",
"_type" : "t_doc",
"_id" : "1",
"_version" : 6,
"found" : true,
"_source" : {
"user" : "Tom",
"flag" : "1",
"msg" : "達に携帯で連絡取ろうと思ったら 電池が切れてて動かない",
"animal" : {
"cat" : "阿猫",
"dog" : "阿狗"
},
"updateUser" : "Jack Ma"
}
}

还可以通过 key-pairs

    /**
* 通过 key-pairs 更新
* @return
* @throws IOException
*/
public static RestHighLevelClient updateOne4() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient(); UpdateRequest request = new UpdateRequest("twitter", "t_doc", "1")
.doc("favorite","二狗","hate","no Money"); UpdateResponse update = client.update(request, RequestOptions.DEFAULT);
System.out.println(update.status().name());
return client;
}

输出:OK

GET twitter/t_doc/
结果:
{
"_index" : "twitter",
"_type" : "t_doc",
"_id" : "1",
"_version" : 7,
"found" : true,
"_source" : {
"user" : "Tom",
"flag" : "1",
"msg" : "達に携帯で連絡取ろうと思ったら 電池が切れてて動かない",
"animal" : {
"cat" : "阿猫",
"dog" : "阿狗"
},
"updateUser" : "Jack Ma",
"hate" : "no Money",
"favorite" : "二狗"
}
}

upserts

    /**
* 存在即更新【输出:OK】
* OK
* {"C":"Carambola","A":"Apple","B":"Banana"}
* 不存在则创建【输出:CREATED】
* CREATED
* {"C":"Carambola"}
* 开启scriptedUpsert【在文档不存在情况下输出:CREATED】
* {"A" : "Apple","B" : "Banana","C" : "Carambola"}
* @return
* @throws IOException
*/
public static RestHighLevelClient upserts() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
UpdateRequest request = new UpdateRequest("twitter", "t_doc", "7")
.script(new Script(ScriptType.INLINE,"painless",
"ctx._source.A='Apple';ctx._source.B='Banana'",Collections.EMPTY_MAP))
// 如果文档不存在,使用upsert方法定义一些内容,这些内容将作为新文档插入
.upsert(jsonBuilder()
.startObject()
.field("C","Carambola")
.endObject());
request.timeout(TimeValue.timeValueSeconds(2)); // 2秒超时
//request.scriptedUpsert(true); // 无论文档是否存在,脚本都必须运行
UpdateResponse update = client.update(request, RequestOptions.DEFAULT);
System.out.println(update.status().name());
return client;
}

--

    /**
* 存在即更新
* OK
* {"C" : "Carambola","A" : "Apple","B" : "Banana","D" : "Dew"}
* 不存在则创建
* CREATED
* {"C" : "Carambola"}
* 开启docAsUpsert【在文档不存在情况下输出:CREATED】
* {"A" : "Apple","B" : "Banana","D" : "Dew"}
* @return
* @throws IOException
*/
public static RestHighLevelClient upserts2() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
UpdateRequest request = new UpdateRequest("twitter", "t_doc", "8")
.doc(jsonBuilder()
.startObject()
.field("A","Apple")
.field("B","Banana")
.field("D","Dew")
.endObject())
// 如果指定docAsUpsert(true),会忽略upsert方法
.upsert(jsonBuilder()
.startObject()
.field("C","Carambola")
.endObject());
//request.docAsUpsert(true); // 如果部分文档尚不存在,则必须将doc用作upsert文档
request.timeout(TimeValue.timeValueSeconds(2)); // 2秒超时
try {
UpdateResponse update = client.update(request, RequestOptions.DEFAULT);
System.out.println(update.status().name());
} catch (ElasticsearchException e) {
if (e.status() == RestStatus.NOT_FOUND) {
// TODO
}
} return client;
}

7. Update By Query API

HTTP请求

# 不更改源数据的前提下更新文档
POST twitter/_update_by_query?conflicts=proceed
结果:
{
"took" : 186,
"timed_out" : false,
"total" : 9,
"updated" : 9,
"deleted" : 0,
"batches" : 1,
"version_conflicts" : 0,
"noops" : 0,
"retries" : {
"bulk" : 0,
"search" : 0
},
"throttled_millis" : ,
"requests_per_second" : -1.0,
"throttled_until_millis" : ,
"failures" : [ ]
}

--

我们有数据:

{
"_index" : "twitter",
"_type" : "t_doc",
"_id" : "9",
"_version" : 3,
"found" : true,
"_source" : {
"flag" : "2",
"user" : "foo"
}
}
# 通过脚本更新
POST twitter/_update_by_query?conflicts=proceed
{
"script": {
"source": "ctx._source.flag++",
"lang": "painless"
},
"query": {
"term": {
"user": "foo"
}
}
}
结果:
{
"took" : 102,
"timed_out" : false,
"total" : 1,
"updated" : 1,
"deleted" : 0,
"batches" : 1,
"version_conflicts" : 0,
"noops" : 0,
"retries" : {
"bulk" : 0,
"search" : 0
},
"throttled_millis" : ,
"requests_per_second" : -1.0,
"throttled_until_millis" : ,
"failures" : [ ]
}

Java

    /**
* 根据查询条件更新
* @return
*/
public static RestHighLevelClient updateByQuery() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
UpdateByQueryRequest request = new UpdateByQueryRequest("twitter");
request.setConflicts("proceed");
request.setQuery(QueryBuilders.matchAllQuery())
.setBatchSize(50) // 批处理大小
.setSize(100) // 限制处理文档的数量
.setScript(new Script(
ScriptType.INLINE, "painless",
"if (ctx._source.flag == '2') {ctx._source.extMsg = '小林さんちのメイドラゴン';}", // 增加一个字段extMsg
Collections.emptyMap()));
BulkByScrollResponse bulkResponse = client.updateByQuery(request, RequestOptions.DEFAULT);
TimeValue timeTaken = bulkResponse.getTook();
boolean timedOut = bulkResponse.isTimedOut();
long totalDocs = bulkResponse.getTotal();
long updatedDocs = bulkResponse.getUpdated();
long deletedDocs = bulkResponse.getDeleted();
long batches = bulkResponse.getBatches();
long noops = bulkResponse.getNoops();
long versionConflicts = bulkResponse.getVersionConflicts();
System.out.println("花费时间:" + timeTaken + ",是否超时:" + timedOut + ",总文档数:" + totalDocs + ",更新数:" +
updatedDocs + ",删除数:" + deletedDocs + ",批量次数:" + batches + ",跳过数:" + noops + ",冲突数:" + versionConflicts);
List<ScrollableHitSource.SearchFailure> searchFailures = bulkResponse.getSearchFailures(); // 搜索期间的故障
searchFailures.forEach(e -> {
System.err.println("Cause:" + e.getReason().getMessage() + "Index:" + e.getIndex() + ",NodeId:" + e.getNodeId() + ",ShardId:" + e.getShardId());
});
List<BulkItemResponse.Failure> bulkFailures = bulkResponse.getBulkFailures(); // 批量索引期间的故障
bulkFailures.forEach(e -> {
System.err.println("Cause:" + e.getCause().getMessage() + "Index:" + e.getIndex() + ",Type:" + e.getType() + ",Id:" + e.getId());
});
return client;
}

结果:【之所以更新了全部文档,是因为matchAllQuery】

花费时间:218ms,是否超时:false,总文档数:9,更新数:9,删除数:0,批量次数:1,跳过数:0,冲突数:0
# 查询flag=的文档
GET /twitter/_search
{
"query": {
"match": {
"flag": "2"
}
}
}
结果:
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 2,
"max_score" : 0.6931472,
"hits" : [
{
"_index" : "twitter",
"_type" : "t_doc",
"_id" : "10",
"_score" : 0.6931472,
"_source" : {
"flag" : "2",
"extMsg" : "小林さんちのメイドラゴン",
"user" : "bar"
}
},
{
"_index" : "twitter",
"_type" : "t_doc",
"_id" : "11",
"_score" : 0.2876821,
"_source" : {
"flag" : "2",
"extMsg" : "小林さんちのメイドラゴン",
"user" : "baz"
}
}
]
}
}

8. Bulk API

HTTP请求

# 批量处理(允许Add,Delete,Update操作)如果包含routing要加上
POST _bulk
{ "delete" : { "_index" : "twitter", "_type" : "t_doc", "_id" : "9" } }
{ "update" : { "_index" : "twitter", "_type" : "t_doc", "_id" : "4","routing":"my_route" } }
{ "doc" : {"user":"new_user"} }
{ "index" : { "_index" : "twitter", "_type" : "t_doc", "_id" : "21" }}
{ "user":"Tom","flag":"1" }
{ "index" : { "_index" : "twitter", "_type" : "t_doc", "_id" : "22" }}
{ "user":"Tony","flag":"1" }
{ "index" : { "_index" : "twitter", "_type" : "t_doc", "_id" : "23" }}
{ "user":"Mary","flag":"1" }
{ "index" : { "_index" : "twitter", "_type" : "t_doc", "_id" : "24" }}
{ "user":"Jerry","flag":"1" }

Java

    /**
* 批量添加
* @return
*/
public static RestHighLevelClient bulkAdd() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
BulkRequest request = new BulkRequest();
request.add(new IndexRequest("twitter", "t_doc", "25")
.source(XContentType.JSON,"user", "Tom","flag","1"));
request.add(new IndexRequest("twitter", "t_doc", "26")
.source(XContentType.JSON,"user", "foo","flag","2"));
request.add(new IndexRequest("twitter", "t_doc", "27")
.source(XContentType.JSON,"user", "bar","flag","2"));
request.add(new IndexRequest("twitter", "t_doc", "28")
.source(XContentType.JSON,"user", "baz","flag","2"));
BulkResponse bulk = client.bulk(request, RequestOptions.DEFAULT);
System.out.println("Status:" + bulk.status().name() + ",hasFailures:" + bulk.hasFailures());
// 下面是multiGet
MultiGetRequest multiGetRequest = new MultiGetRequest()
.add(new MultiGetRequest.Item("twitter", "t_doc", "25"))
.add(new MultiGetRequest.Item("twitter", "t_doc", "26"))
.add(new MultiGetRequest.Item("twitter", "t_doc", "27"))
.add(new MultiGetRequest.Item("twitter", "t_doc", "28"));
MultiGetResponse response = client.mget(multiGetRequest, RequestOptions.DEFAULT);
MultiGetItemResponse[] itemResponses = response.getResponses();
for(MultiGetItemResponse r : itemResponses){
System.out.println(r.getResponse().getSourceAsString());
}
return client;
}

输出:

Status:OK,hasFailures:false
{"user":"Tom","flag":"1"}
{"user":"foo","flag":"2"}
{"user":"bar","flag":"2"}
{"user":"baz","flag":"2"}

也可以批量更新

    /**
* 批量更新
* @return
*/
public static RestHighLevelClient bulkUpdate() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
BulkRequest request = new BulkRequest();
// 更新
request.add(new UpdateRequest("twitter", "t_doc", "27")
.doc(XContentType.JSON,"field", "foo","color", "red","size", "100"));
// 添加
request.add(new IndexRequest("twitter", "t_doc", "29")
.source(XContentType.JSON,"field", "bar","color", "blue","size", "200"));
// 删除
request.add(new DeleteRequest("twitter", "t_doc", "28"));
BulkResponse bulk = client.bulk(request, RequestOptions.DEFAULT);
System.out.println("Status:" + bulk.status().name() + ",hasFailures:" + bulk.hasFailures()); // 针对不同类型进行处理
for (BulkItemResponse bulkItemResponse : bulk) {
DocWriteResponse itemResponse = bulkItemResponse.getResponse(); if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.INDEX
|| bulkItemResponse.getOpType() == DocWriteRequest.OpType.CREATE) {
IndexResponse indexResponse = (IndexResponse) itemResponse;
System.out.println(indexResponse.status().name());
} else if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.UPDATE) {
UpdateResponse updateResponse = (UpdateResponse) itemResponse;
System.out.println(updateResponse.status().name());
} else if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.DELETE) {
DeleteResponse deleteResponse = (DeleteResponse) itemResponse;
System.out.println(deleteResponse.status().name());
}
} String[] includes = Strings.EMPTY_ARRAY;
String[] excludes = new String[] {"flag"};
// 包含/排除的字段
FetchSourceContext fetchSourceContext =
new FetchSourceContext(true, includes, excludes);
MultiGetRequest multiGetRequest = new MultiGetRequest()
.add(new MultiGetRequest.Item("twitter", "t_doc", "29").fetchSourceContext(fetchSourceContext))
.add(new MultiGetRequest.Item("twitter", "t_doc", "28").fetchSourceContext(fetchSourceContext))
.add(new MultiGetRequest.Item("twitter", "t_doc", "27").fetchSourceContext(fetchSourceContext)); MultiGetResponse response = client.mget(multiGetRequest, RequestOptions.DEFAULT);
MultiGetItemResponse[] itemResponses = response.getResponses();
for(MultiGetItemResponse r : itemResponses){
System.out.println(r.getResponse().getSourceAsString());
}
return client;
}

输出:

Status:OK,hasFailures:false
OK
CREATED
OK
{"field":"bar","color":"blue","size":"200"}
null
{"field":"foo","color":"red","size":"100","user":"bar"}

bulkProcessor就比较厉害了

    /**
* BulkProcessor通过提供一个实用程序类来简化Bulk API的使用,它允许索引/更新/删除操作在添加到处理器时透明地执行。
* 为了执行请求,BulkProcessor需要以下组件:
* RestHighLevelClient
* 此客户端用于执行BulkRequest和检索BulkResponse
* BulkProcessor.Listener
* 在每个BulkRequest执行之前和之后,或者在BulkRequest失败时,都会调用这个侦听器
* BulkProcessor.builder方法可用于构建新的BulkProcessor:
* @return
*/
public static RestHighLevelClient bulkProcessor() throws InterruptedException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient(); BulkProcessor.Listener listener = new BulkProcessor.Listener() {
@Override
public void beforeBulk(long executionId, BulkRequest request) {
int numberOfActions = request.numberOfActions();
System.out.println("请求数量:" + numberOfActions);
} @Override
public void afterBulk(long executionId, BulkRequest request, BulkResponse response) {
if (response.hasFailures()) {
System.out.println("Bulk Failures,ID:" + executionId + ",Status:" + response.status().name());
for (BulkItemResponse bulkItemResponse : response) {
if (bulkItemResponse.isFailed()) {
BulkItemResponse.Failure failure = bulkItemResponse.getFailure();
System.err.println(failure.getCause().getMessage());
}
}
} else {
System.out.println("Bulk "+ executionId +" Complete in" + response.getTook().getMillis() + "s");
}
} @Override
public void afterBulk(long executionId, BulkRequest request, Throwable failure) {
System.out.println("Failed to execute bulk:" + failure);
}
}; BiConsumer<BulkRequest, ActionListener<BulkResponse>> bulkConsumer =
(request, bulkListener) -> client.bulkAsync(request, RequestOptions.DEFAULT, bulkListener);
BulkProcessor bulkProcessor = BulkProcessor.builder(bulkConsumer, listener)
.setBulkActions(500) // 请求(Index,Update,Delete)的数量达到500,就刷新一次bulk request【默认1000】
// .setBulkSize(new ByteSizeValue(1L, ByteSizeUnit.MB)) // 累计请求所占的空间达到1M,就刷新一次bulk request【默认5M】
.setConcurrentRequests(0) // 设置允许执行的并发请求数量(默认为1,使用0只允许执行单个请求)
// .setFlushInterval(TimeValue.timeValueSeconds(10L)) // 每隔一段时间刷新一次【默认未设置】
.setBackoffPolicy(BackoffPolicy
.constantBackoff(TimeValue.timeValueSeconds(1L), 3))// 设置一个初始等待1秒并重试3次的Backoff策略
.build();
for(int i = 1; i <= 2000; i++){
bulkProcessor.add(new IndexRequest("books", "java", ""+i)
.source(XContentType.JSON,"title","title_"+i,"user","user_"+i));
} bulkProcessor.flush();
Thread.sleep(2000);
bulkProcessor.close();
return client;
}

输出:【警告可忽略,因为默认分片数量在7.0.0版本会改变,这里提醒一下用户。也就是说,最好先去建立索引(设置好参数),再来添加数据】

请求数量:500
十二月 25, 2018 11:24:06 上午 org.elasticsearch.client.RestClient logResponse
警告: request [POST http://localhost:9200/_bulk?timeout=1m] returned 1 warnings: [299 Elasticsearch-6.5.0-816e6f6 "the default number of shards will change from [5] to [1] in 7.0.0; if you wish to continue using the default of [5] shards, you must manage this on the create index request or with an index template" "Tue, 25 Dec 2018 03:24:04 GMT"]
Bulk 1 Complete in2044s
请求数量:500
Bulk 2 Complete in333s
请求数量:500
Bulk 3 Complete in235s
请求数量:500
Bulk 4 Complete in244s

查看:

GET books/_search
结果:
{
"took" : 18,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 2000,
"max_score" : 1.0,
"hits" : [
{
"_index" : "books",
"_type" : "java",
"_id" : "14",
"_score" : 1.0,
"_source" : {
"title" : "title_14",
"user" : "user_14"
}
},
....
]
}
}

9. Multi-Get API

HTTP 请求

GET /_mget
{
"docs" : [
{
"_index" : "books",
"_type" : "java",
"_id" : "1"
},
{
"_index" : "twitter",
"_type" : "t_doc",
"_id" : "1"
}
]
}
结果:
{
"docs" : [
{
"_index" : "books",
"_type" : "java",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : {
"title" : "title_1",
"user" : "user_1"
}
},
{
"_index" : "twitter",
"_type" : "t_doc",
"_id" : "1",
"_version" : 13,
"found" : true,
"_source" : {
"msg" : "達に携帯で連絡取ろうと思ったら 電池が切れてて動かない",
"flag" : "1",
"user" : "new_name"
}
}
]
}
GET /twitter/t_doc/_mget
{
"docs" : [
{
"_id" : "1"
},
{
"_id" : "2"
}
]
}
GET /twitter/t_doc/_mget
{
"ids" : ["1", "2"]
}
# 两个方式效果一样
结果:
{
"docs" : [
{
"_index" : "twitter",
"_type" : "t_doc",
"_id" : "1",
"_version" : 13,
"found" : true,
"_source" : {
"msg" : "達に携帯で連絡取ろうと思ったら 電池が切れてて動かない",
"flag" : "1",
"user" : "new_name"
}
},
{
"_index" : "twitter",
"_type" : "t_doc",
"_id" : "2",
"_version" : 5,
"found" : true,
"_source" : {
"counter" : 5,
"user" : "new_user"
}
}
]
}

 Java代码在bulk里面有体现,这里就不赘述了。

10. Reindex API

Reindex不尝试设置目标索引。它不复制源索引的设置。您应该在运行_reindex操作之前设置目标索引,包括设置映射、碎片计数、副本等。

# 复制源索引twitter到目标索引new_twitter
POST _reindex
{
"source": {
"index": "twitter"
},
"dest": {
"index": "new_twitter"
}
}
结果:
{
"took" : 1626,
"timed_out" : false,
"total" : 16,
"updated" : 0,
"created" : 16,
"deleted" : 0,
"batches" : 1,
"version_conflicts" : 0,
"noops" : 0,
"retries" : {
"bulk" : 0,
"search" : 0
},
"throttled_millis" : ,
"requests_per_second" : -1.0,
"throttled_until_millis" : ,
"failures" : [ ]
}
# 查询
GET /new_twitter/_search
结果:
{
"took" : 9,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 16,
"max_score" : 1.0,
"hits" : [
{
"_index" : "new_twitter",
"_type" : "t_doc",
"_id" : "22",
"_score" : 1.0,
"_source" : {
"user" : "Tony",
"flag" : "1"
}
},
...
]
}
}

为了避免出现冲突导致进程停止,指定:conflicts:proceed

POST _reindex
{
"conflicts": "proceed",
"source": {
"index": "twitter"
},
"dest": {
"index": "new_twitter",
"op_type": "create"
}
}

还可以查询出指定的内容,然后送进目标索引

POST _reindex
{
"source": {
"index": "twitter",
"type": "t_doc",
"query": {
"term": {
"user": "kimchy"
}
}
},
"dest": {
"index": "new_twitter"
}
}

和可以合并多个索引到目标索引

#合并两个索引,跳过冲突【conflicts】,只转移10000条数据【size】
POST _reindex
{
"conflicts": "proceed",
"size": 10000,
"source": {
"index": ["twitter", "new_twitter"],
"type": ["t_doc", "post"]
},
"dest": {
"index": "all_together",
"type": "all_doc"
}
}

还可以使用脚本、从远程服务器reindex、修改目标字段名称,请参考官方文档

Java

    /**
* reIndex可用于将文档从一个或多个索引复制到目标索引
* DocWriteRequest.OpType.CREATE 跳过已有的文档
* DocWriteRequest.OpType.INDEX 已有相同id的会被覆盖
* @return
*/
public static RestHighLevelClient reIndex() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
ReindexRequest reindexRequest = new ReindexRequest()
.setSourceIndices("twitter","new_twitter")
.setDestIndex("all_together")
.setDestOpType(DocWriteRequest.OpType.INDEX.getLowercase())
.setDestDocType("all_doc")
// .setSize(10) // copy的文档数
// .setScript(new Script(ScriptType.INLINE, "painless",
// "if (ctx._source.user == 'kimchy') {ctx._source.likes++;}",
// Collections.emptyMap())) // 脚本
.setSourceBatchSize(500); // 默认批量为1000,你可以自己设置批次获取的数量
reindexRequest.setConflicts("proceed"); // 默认情况下,版本冲突会中止_reindex进程(abort)
BulkByScrollResponse bulkResponse = client.reindex(reindexRequest, RequestOptions.DEFAULT);
TimeValue timeTaken = bulkResponse.getTook();
boolean timedOut = bulkResponse.isTimedOut();
long totalDocs = bulkResponse.getTotal();
long updatedDocs = bulkResponse.getUpdated();
long createdDocs = bulkResponse.getCreated();
long deletedDocs = bulkResponse.getDeleted();
long batches = bulkResponse.getBatches();
long noops = bulkResponse.getNoops(); // 跳过的文档数
long versionConflicts = bulkResponse.getVersionConflicts(); // 版本冲突的数量
long bulkRetries = bulkResponse.getBulkRetries(); // bulk重试次数
long searchRetries = bulkResponse.getSearchRetries(); // 搜索重试次数
System.out.println("花费时间:" + timeTaken + ",是否超时:" + timedOut + ",总文档数:" + totalDocs + ",更新数:" +
updatedDocs + ",创建数:" + createdDocs + ",删除数:" + deletedDocs + ",批量次数:" + batches + ",跳过数:" +
noops + ",冲突数:" + versionConflicts + ",bulk重试次数:" + bulkRetries + ",搜索重试次数:" + searchRetries);
List<ScrollableHitSource.SearchFailure> searchFailures = bulkResponse.getSearchFailures(); // 搜索期间的故障
searchFailures.forEach(e -> {
System.err.println("Cause:" + e.getReason().getMessage() + "Index:" + e.getIndex() + ",NodeId:" + e.getNodeId() + ",ShardId:" + e.getShardId());
});
List<BulkItemResponse.Failure> bulkFailures = bulkResponse.getBulkFailures(); // 批量索引期间的故障
bulkFailures.forEach(e -> {
System.err.println("Cause:" + e.getCause().getMessage() + "Index:" + e.getIndex() + ",Type:" + e.getType() + ",Id:" + e.getId());
});
return client;
}

因为这两个索引内容一样,所以会出现 更新数:16,创建数:16

花费时间:1.6s,是否超时:false,总文档数:32,更新数:16,创建数:16,删除数:0,批量次数:1,跳过数:0,冲突数:0,bulk重试次数:0,搜索重试次数:0

查看目标索引(总文档数16

GET /all_together/_search
结果:
{
"took" : 4,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 16,
"max_score" : 1.0,
"hits" : [
{
"_index" : "all_together",
"_type" : "all_doc",
"_id" : "22",
"_score" : 1.0,
"_source" : {
"user" : "Tony",
"flag" : "1"
}
},
...
]
}
}

--

11. Query

HTTP请求

RequestBodySearch 示例

# sort--mode:min、max、sum、avg、median
# sort--order:asc、desc
# 过滤_source:如果要禁用,"_source": false
# Doc格式化:https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-docvalue-fields.html
# 高亮参数:写在外面是全局的,写在field里面是局部的
GET /_search
{
"query" : {
"term" : { "user" : "Tony" }
},
"_source": [ "obj1.*", "obj2.*" ],
"from" : , "size" : ,
"sort" : [
{"price" : {"order" : "asc", "mode" : "avg"}}
],
"script_fields" : {
"my_field1" : {
"script" : {
"lang": "painless",
"source": "doc['flag'].value * params.factor",
"params" : {
"factor" : 2.0
}
}
}
},
"docvalue_fields" : [
{
"field": "postDate",
"format": "yyyy-MM-dd"
}
],
"highlight" : {
"order" : "score",
"pre_tags" : ["<tag1>"],
"post_tags" : ["</tag1>"],
"fields" : {
"_all" : {},
"message" : {"fragment_size" : 150, "number_of_fragments" : 3}
}
}
}

QueryDSL

**Match 与 Match Phrase【这里使用了ik分词器

# 准备测试数据
PUT test
{
"settings" : {
"number_of_shards" : 1,
"number_of_replicas" : 1
},
"mappings" : {
"msg" : {
"properties" : {
"message" : { "type" : "text","analyzer": "ik_max_word" }
}
}
}
}
PUT test/msg/
{"message" : "她过山车一般的跌宕人生,成了 2018 年我听过的最精彩、也最让人感叹唏嘘的真人真事。"}
PUT test/msg/
{"message" : "她就是我们今天的主人公,伊丽莎白·福尔摩斯(Elizabeth Holmes)。"}
# match query
GET /_search
{
"query": {
"match" : {
"message" : {
"query" : "今天的主人公",
"analyzer" : "ik_max_word"
}
}
}
} # Match Phrase Query 短语查询
GET /_search
{
"query": {
"match_phrase" : {
"message" : {
"query" : "今天的主人公",
"analyzer" : "ik_max_word"
}
}
}
}

执行match的结果:

执行match phrase的结果

分词器:

POST _analyze
{
"analyzer": "ik_max_word",
"text": "今天的主人公"
}
---
{
"tokens" : [
{
"token" : "今天",
"start_offset" : 0,
"end_offset" : 2,
"type" : "CN_WORD",
"position" : 0
},
{
"token" : "的",
"start_offset" : 2,
"end_offset" : 3,
"type" : "CN_CHAR",
"position" : 1
},
{
"token" : "主人公",
"start_offset" : 3,
"end_offset" : 6,
"type" : "CN_WORD",
"position" : 2
},
{
"token" : "主人",
"start_offset" : 3,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 3
},
{
"token" : "公",
"start_offset" : 5,
"end_offset" : 6,
"type" : "CN_CHAR",
"position" : 4
}
]
}

结论:match会查出包含所有token的结果,而matchPhrase则只会查询“今天的主人公”这一个词组

**Match Phrase Prefix Query,短语前缀查询,顾名思义:以查询关键字为前缀的查询

# Match Phrase Prefix Query 短语前缀查询
GET /_search
{
"query": {
"match_phrase_prefix" : {
"message" : {
"query" : "她就是",
"analyzer" : "ik_max_word"
}
}
}
}
---
{
"took" : 9,
"timed_out" : false,
"_shards" : {
"total" : 28,
"successful" : 28,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 3.2103658,
"hits" : [
{
"_index" : "test",
"_type" : "msg",
"_id" : "101",
"_score" : 3.2103658,
"_source" : {
"message" : "她就是我们今天的主人公,伊丽莎白·福尔摩斯(Elizabeth Holmes)。"
}
}
]
}
}

**Query String Query

# 字符串查询 如果多个字段:"fields" : ["content", "name"] 代替default_field
GET /_search
{
"query": {
"query_string" : {
"default_field" : "message",
"query" : "(过山车) OR (伊丽莎白)"
}
}
}
---
{
"took" : 5,
"timed_out" : false,
"_shards" : {
"total" : 28,
"successful" : 28,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 2,
"max_score" : 0.80259144,
"hits" : [
{
"_index" : "test",
"_type" : "msg",
"_id" : "101",
"_score" : 0.80259144,
"_source" : {
"message" : "她就是我们今天的主人公,伊丽莎白·福尔摩斯(Elizabeth Holmes)。"
}
},
{
"_index" : "test",
"_type" : "msg",
"_id" : "100",
"_score" : 0.6099695,
"_source" : {
"message" : "她过山车一般的跌宕人生,成了 2018 年我听过的最精彩、也最让人感叹唏嘘的真人真事。"
}
}
]
}
}

以下查询的字段类型都为keyword,适合精确查询

**TermQuery

# Term Query 适合关键字的查询,字段类型为keyword
GET /_search
{
"query": {
"term": {
"exact_value": "Quick Foxes!"
}
}
}

**Terms Query

# Terms Query 对同一个字段匹配多个关键字
GET /_search
{
"query": {
"terms" : { "user" : ["kimchy", "elasticsearch"]}
}
}

**Range Query

# Range Query 范围查询【gt:大于,gte:大于等于,lt:小于,lte:小于等于】
GET _search
{
"query": {
"range" : {
"age" : {
"gte" : 10,
"lte" : 20,
"boost" : 2.0
}
}
}
}
# Range Query 日期【y-年,M-月,w-周,d-日,h-小时,H-小时,m-分钟,s-秒。+1h:+小时,-1d:-天,/d:四舍五入到最近的日期,now:当前时间】比如:now = -- :: now/d = -- ::
GET _search
{
"query": {
"range" : {
"date" : {
"gte" : "now-1d/d",
"lt" : "now/d"
}
}
}
}
GET _search
{
"query": {
"range" : {
"birthday" : {
"gte": "01/01/2012",
"lte": "2013",
"format": "dd/MM/yyyy||yyyy"
}
}
}
}

**Exists Query

# Exist Query 返回在原始字段 message 中至少有一个非空值的文档
GET /_search
{
"query": {
"exists" : { "field" : "message" }
}
}

**Prefix Query

# Prefix Query 前缀查询
GET /_search
{ "query": {
"prefix" : { "user" : "ki" }
}
}

**Wildcard Query

# Wildcard Query 不建议以通配符开头,因为那样性能最低
GET /_search
{
"query": {
"wildcard" : { "user" : "ki*y" }
}
}

**Regexp Query

# Regexp Query 正则查询,你可以使用任何正则表达式,同样不建议以通配符开头
GET /_search
{
"query": {
"regexp":{
"name.first": "s.*y"
}
}
}

**Fuzzy Query

# Fuzzy Query 模糊查询【与SQL的模糊查询不一样,更多信息请自行查阅资料】
GET /_search
{
"query": {
"fuzzy" : { "user" : "ki" }
}
}

**Type Query

# Type Query 查询type下的所有文档
GET /_search
{
"query": {
"type" : {
"value" : "t_doc"
}
}
}

**Ids Query

# Ids Query 根据id列表查询
GET /_search
{
"query": {
"ids" : {
"type" : "t_doc",
"values" : ["1", "4", "100"]
}
}
}

下面是复合查询

# bool查询【它有must、filter、should、must_not四个可选条件】
POST _search
{
"query": {
"bool" : {
"must" : {
"term" : { "user" : "kimchy" }
},
"filter": {
"term" : { "tag" : "tech" }
},
"must_not" : {
"range" : {
"age" : { "gte" : 10, "lte" : 20 }
}
},
"should" : [
{ "term" : { "tag" : "wow" } },
{ "term" : { "tag" : "elasticsearch" } }
],
"minimum_should_match" : ,
"boost" : 1.0
}
}
}

下面是地理查询,初始化数据 参见 19.2 geo_bounding_box查询 地图选点:这里

**地理边界查询【根据两个点确定的矩形,查询落在矩形内的坐标】

# 地理边界查询
GET /china_index/_search
{
"query": {
"bool" : {
"must" : {
"match_all" : {}
},
"filter" : {
"geo_bounding_box" : {
"location" : {
"top_left" : "23.1706638271,113.0383300781",
"bottom_right" : "22.9760953044,113.5025024414"
}
}
}
}
}
}

结果:

**地理半径查询【根据指定的坐标为中心,查询半径范围内的坐标】

# 地理半径查询
GET /china_index/_search
{
"query": {
"bool" : {
"must" : {
"match_all" : {}
},
"filter" : {
"geo_distance" : {
"distance" : "20km",
"location" : {
"lat" : 39.6733703918,
"lon" : 116.4111328125
}
}
}
}
}
}
---
{
"took" : 6,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 1.0,
"hits" : [
{
"_index" : "china_index",
"_type" : "city",
"_id" : "150",
"_score" : 1.0,
"_source" : {
"pName" : "北京市",
"cName" : "大兴区",
"location" : {
"lat" : 39.72684,
"lon" : 116.34159
}
}
}
]
}
}

**地理多边形查询【查找指定的坐标围成的多边形内的坐标】

# 地理多边形查询
GET /china_index/_search
{
"query": {
"bool" : {
"must" : {
"match_all" : {}
},
"filter" : {
"geo_polygon" : {
"location" : {
"points" : [
"20.4270128143,110.2807617188",
"19.6632802200,109.7094726563",
"19.6839702359,110.8520507813"
]
}
}
}
}
}
}
---
{
"took" : 39,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 4,
"max_score" : 1.0,
"hits" : [
{
"_index" : "china_index",
"_type" : "city",
"_id" : "1555",
"_score" : 1.0,
"_source" : {
"pName" : "海南省",
"cName" : "海口",
"location" : {
"lat" : 20.02,
"lon" : 110.35
}
}
},
{
"_index" : "china_index",
"_type" : "city",
"_id" : "1556",
"_score" : 1.0,
"_source" : {
"pName" : "海南省",
"cName" : "琼山",
"location" : {
"lat" : 19.98,
"lon" : 110.33
}
}
},
{
"_index" : "china_index",
"_type" : "city",
"_id" : "1558",
"_score" : 1.0,
"_source" : {
"pName" : "海南省",
"cName" : "定安",
"location" : {
"lat" : 19.68,
"lon" : 110.31
}
}
},
{
"_index" : "china_index",
"_type" : "city",
"_id" : "1562",
"_score" : 1.0,
"_source" : {
"pName" : "海南省",
"cName" : "澄迈",
"location" : {
"lat" : 19.75,
"lon" : 110.0
}
}
}
]
}
}

**地理形状查询 geo_shape【这个资料比较少,所以我重点研究了一下】

# 存储地理形状的索引
# tree参数:geohash和quadtree,默认geohash
# strategy参数:recursive和term,默认recursive【支持查询:INTERSECTS,DISJOINT,WITHIN,CONTAINS】
# precision参数:精度,单位有in, inch, yd, yard, mi, miles, km, kilometers, m,meters, cm,centimeters, mm, millimeters
# 形状类型解释 | GeoJSON Type | WKT Type | Elasticsearch Type
# 单个地理坐标 Point POINT point
# 给出两个或多个点的任意一条线 LineString LINESTRING linestring
# 闭合的多边形,第一个和最后一个点必须匹配 Polygon POLYGON polygon
# 一系列未连接但可能相关的点 MultiPoint MULTIPOINT multipoint
# 一系列独立的线 MultiLineString MULTILINESTRING multilinestring
# 一系列单独的多边形 MultiPolygon MULTIPOLYGON multipolygon
# 类似于multi系列,但是多种类型不可以共存 GeometryCollection GEOMETRYCOLLECTION geometrycollection
# 仅指定左上角和右下角的矩形 无 BBOX envelope
# 指定中心和半径的圆,默认单位是米 无 无 circle
PUT china_shape_index
{
"settings" : {
"number_of_shards" : 1,
"number_of_replicas" : 1
},
"mappings" : {
"info" : {
"properties" : {
"remark" : { "type" : "keyword" },
"location" : {
"type" : "geo_shape",
"tree" : "geohash",
"precision": "100m"
}
}
}
}
}

添加不同类型的数据

# 注意,如果是数组[经度,纬度]
# 添加一个点
POST /china_shape_index/info
{
"location" : {
"type" : "point",
"coordinates" : [109.1162109375,37.2653099556]
}
}
# 添加一条线
POST /china_shape_index/info
{
"location" : {
"type" : "linestring",
"coordinates" : [[109.1162109375,37.2653099556], [117.6855468750,35.5322262277]]
}
}
# 添加一个形状【我画了个三角形】
POST /china_shape_index/info
{
"location" : {
"type" : "polygon",
"coordinates" : [
[ [114.0380859375, 31.9148675033], [116.6748046875, 30.0690939644],
[111.4453125000,29.7643773752], [114.0380859375, 31.9148675033] ]
]
}
}
# 多个坐标
POST /china_shape_index/info
{
"location" : {
"type" : "multipoint",
"coordinates" : [
[111.4453125000,29.7643773752], [117.6855468750,35.5322262277]
]
}
}
# 由leftTop和bottomRight围成的矩形
POST /china_shape_index/info
{
"location" : {
"type" : "envelope",
"coordinates" : [ [120.2783203125,25.2049411536], [122.2119140625,23.4430889311] ]
}
}
# 圆形
POST /china_shape_index/info
{
"location" : {
"type" : "circle",
"coordinates" : [116.5429687500,39.7071866568],
"radius" : "10km"
}
}

形状查询【这里与我们测试数据(以北京为中心画一个圆)相交了】

# 查询相交的形状。relation可选:intersects, disjoint, within, contains【相交,不相交,内部,包含】
GET /china_shape_index/_search
{
"query":{
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_shape": {
"location": {
"shape": {
"type": "envelope",
"coordinates" : [[114.9169921875,40.5137991550], [118.6083984375,38.7883453551]]
},
"relation": "intersects"
}
}
}
}
}
}
---
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 1.0,
"hits" : [
{
"_index" : "china_shape_index",
"_type" : "info",
"_id" : "FbvH82cBOwlg01SCD5ab",
"_score" : 1.0,
"_source" : {
"location" : {
"type" : "circle",
"coordinates" : [
116.54296875,
39.7071866568
],
"radius" : "10km"
}
}
}
]
}
}

..

Java【太多了,我只选择部分示例】

全文索引系列:matchQuery、matchAllQuery、matchPhraseQuery、matchPhrasePrefixQuery、multiMatchQuery、commonTermsQuery、queryStringQuery

Term系列:termQuery、termsQuery、rangeQuery、existsQuery、prefixQuery、wildcardQuery、regexpQuery、fuzzyQuery、typeQuery、idsQuery

地理系列:geoDistanceQuery、geoBoundingBoxQuery、geoPolygonQuery、geoShapeQuery

--

    /**
* matchQuery
* 排序,高亮查询
* @return
* @throws IOException
*/
public static RestHighLevelClient search() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
try {
SearchResponse search = client.search(new SearchRequest("test")
.source(new SearchSourceBuilder()
.query(QueryBuilders.matchQuery("message", "今天的主人公"))
.sort("_score", SortOrder.DESC) // 根据分数倒序排序
.from(0) // 返回结果开始位置
.size(5) // 返回结果数量
.timeout(TimeValue.timeValueSeconds(10)) // 超时
.highlighter(new HighlightBuilder()
.field("message",200)
.preTags("<pre>").postTags("</pre>"))
), RequestOptions.DEFAULT);
System.out.println("Hits:" + search.getHits().totalHits);
search.getHits().forEach(e -> {
System.out.println("分数:" + e.getScore() + ",结果:" + e.getSourceAsString());
Map<String, HighlightField> highlightFields = e.getHighlightFields();
for (String key : highlightFields.keySet()){
HighlightField field = highlightFields.get(key);
System.out.println(key + ":" + field.fragments()[0]/* + "," + field.fragments().length*/);
} });
} catch (ElasticsearchException e) {
if(e.status() == RestStatus.NOT_FOUND){
// TODO
System.out.println("Index Not Found-" + e.getIndex());
}
}
return client;
}

输出:

Hits:
分数:3.421475,结果:{"message":"她就是我们今天的主人公,伊丽莎白·福尔摩斯(Elizabeth Holmes)。"}
message:她就是我们<pre>今天</pre><pre>的</pre><pre>主人</pre><pre>公</pre>,伊丽莎白·福尔摩斯(Elizabeth Holmes)。
分数:0.26740497,结果:{"message":"她过山车一般的跌宕人生,成了 2018 年我听过的最精彩、也最让人感叹唏嘘的真人真事。"}
message:她过山车一般<pre>的</pre>跌宕人生,成了 年我听过<pre>的</pre>最精彩、也最让人感叹唏嘘<pre>的</pre>真人真事。

--

    /**
* matchPhraseQuery
* 排序,高亮查询
* @return
* @throws IOException
*/
public static RestHighLevelClient search() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
try {
SearchResponse search = client.search(new SearchRequest("test")
.source(new SearchSourceBuilder()
.query(QueryBuilders.matchPhraseQuery("message", "今天的主人公"))
.sort("_score", SortOrder.DESC) // 根据分数倒序排序
.from(0) // 返回结果开始位置
.size(5) // 返回结果数量
.timeout(TimeValue.timeValueSeconds(10)) // 超时
.highlighter(new HighlightBuilder()
.field("message",200)
.preTags("<pre>").postTags("</pre>"))
), RequestOptions.DEFAULT);
System.out.println("Hits:" + search.getHits().totalHits);
search.getHits().forEach(e -> {
System.out.println("分数:" + e.getScore() + ",结果:" + e.getSourceAsString());
Map<String, HighlightField> highlightFields = e.getHighlightFields();
for (String key : highlightFields.keySet()){
HighlightField field = highlightFields.get(key);
System.out.println(key + ":" + field.fragments()[0]/* + "," + field.fragments().length*/);
} });
} catch (ElasticsearchException e) {
if(e.status() == RestStatus.NOT_FOUND){
// TODO
System.out.println("Index Not Found-" + e.getIndex());
}
}
return client;
}

结果:

Hits:
分数:3.421475,结果:{"message":"她就是我们今天的主人公,伊丽莎白·福尔摩斯(Elizabeth Holmes)。"}
message:她就是我们<pre>今天</pre><pre>的</pre><pre>主人</pre><pre>公</pre>,伊丽莎白·福尔摩斯(Elizabeth Holmes)。

--

    /**
* queryStringQuery
* 排序,高亮查询
* @return
* @throws IOException
*/
public static RestHighLevelClient search() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
try {
SearchResponse search = client.search(new SearchRequest("test")
.source(new SearchSourceBuilder()
.query(QueryBuilders.queryStringQuery("今天的主人公").field("message"))
.sort("_score", SortOrder.DESC) // 根据分数倒序排序
.from(0) // 返回结果开始位置
.size(5) // 返回结果数量
.timeout(TimeValue.timeValueSeconds(10)) // 超时
.highlighter(new HighlightBuilder()
.field("message",200)
.preTags("<pre>").postTags("</pre>"))
), RequestOptions.DEFAULT);
System.out.println("Hits:" + search.getHits().totalHits);
search.getHits().forEach(e -> {
System.out.println("分数:" + e.getScore() + ",结果:" + e.getSourceAsString());
Map<String, HighlightField> highlightFields = e.getHighlightFields();
for (String key : highlightFields.keySet()){
HighlightField field = highlightFields.get(key);
System.out.println(key + ":" + field.fragments()[0]/* + "," + field.fragments().length*/);
} });
} catch (ElasticsearchException e) {
if(e.status() == RestStatus.NOT_FOUND){
// TODO
System.out.println("Index Not Found-" + e.getIndex());
}
}
return client;
}

结果:

Hits:
分数:3.421475,结果:{"message":"她就是我们今天的主人公,伊丽莎白·福尔摩斯(Elizabeth Holmes)。"}
message:她就是我们<pre>今天</pre><pre>的</pre><pre>主人</pre><pre>公</pre>,伊丽莎白·福尔摩斯(Elizabeth Holmes)。
分数:0.26740497,结果:{"message":"她过山车一般的跌宕人生,成了 2018 年我听过的最精彩、也最让人感叹唏嘘的真人真事。"}
message:她过山车一般<pre>的</pre>跌宕人生,成了 年我听过<pre>的</pre>最精彩、也最让人感叹唏嘘<pre>的</pre>真人真事。

下面测试term系列

# 准备测试数据
PUT users
{
"settings" : {
"number_of_shards" : 1,
"number_of_replicas" : 1
},
"mappings" : {
"info" : {
"properties" : {
"username" : { "type" : "keyword" },
"address" : { "type" : "text","analyzer": "ik_max_word" }
}
}
}
}
PUT users/info/
{"username" : "孙行者","address" : "软件产业基地1栋B座大堂","age": 15}
PUT users/info/
{"username" : "孙大圣","address" : "万达北路710号戈雅公寓105号商铺","age": 26}
PUT users/info/
{"username" : "西蒙·胡塞·德·拉·桑迪西玛·特里尼达·玻利瓦尔·帕拉修斯·伊·布兰科","address" : "滨河大道7009号","age": 7}
PUT users/info/
{"username" : "奥斯特洛夫斯基","address" : "光谷二路225号食堂","age": 30}
PUT users/info/
{"username" : "Brfxxccxxmnpcccclllmmnprxvclmnckssqlbb1111b","address" : "海淀紫竹院路甲2号商业05号","age": 18}
# 查看
GET /users/_search

--

    /**
* termQuery
* rangeQuery
* prefixQuery
* wildcardQuery
* @return
* @throws IOException
*/
public static RestHighLevelClient termSearch() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
SearchRequest request = new SearchRequest("users");
String[] includeFields = new String[] {"username", "age"};
String[] excludeFields = new String[] {"addr*"};
request.source(new SearchSourceBuilder()
// 关键字查询
//.query(QueryBuilders.termsQuery("username", "奥斯特洛夫斯基"))
// 范围查询
//.query(QueryBuilders.rangeQuery("age").lt(20))
// 前缀查询
//.query(QueryBuilders.prefixQuery("username", "孙"))
// 通配符查询
.query(QueryBuilders.wildcardQuery("username", "西蒙*"))
.fetchSource(includeFields, excludeFields) // 过滤源
.from(0)
.size(5)
.sort("age", SortOrder.ASC)
);
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
System.out.println("Hits:" + search.getHits().totalHits);
search.getHits().forEach(e -> {
System.out.println(e.getSourceAsString());
});
return client;
}

结果:

Hits:
{"age":7,"username":"西蒙·胡塞·德·拉·桑迪西玛·特里尼达·玻利瓦尔·帕拉修斯·伊·布兰科"}

下面测试聚合查询 Aggregation

    /**
* 聚合查询
* @return
* @throws IOException
*/
public static RestHighLevelClient aggSearch() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
SearchRequest request = new SearchRequest("users");
request.source(new SearchSourceBuilder()
.query(QueryBuilders.matchAllQuery())
.aggregation(AggregationBuilders.avg("ageAVG").field("age"))
.from(0)
.size(5)
.sort("age", SortOrder.ASC)
);
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
System.out.println("Hits:" + search.getHits().totalHits);
search.getHits().forEach(e -> {
System.out.println(e.getSourceAsString());
});
Avg avg = search.getAggregations().get("ageAVG");
System.out.println("平均值:" + avg.getValue());
return client;
}

结果:

Hits:
{"username":"西蒙·胡塞·德·拉·桑迪西玛·特里尼达·玻利瓦尔·帕拉修斯·伊·布兰科","address":"滨河大道7009号","age":7}
{"username":"孙行者","address":"软件产业基地1栋B座大堂","age":15}
{"username":"Brfxxccxxmnpcccclllmmnprxvclmnckssqlbb1111b","address":"海淀紫竹院路甲2号商业05号","age":18}
{"username":"孙大圣","address":"万达北路710号戈雅公寓105号商铺","age":26}
{"username":"奥斯特洛夫斯基","address":"光谷二路225号食堂","age":30}
平均值:19.2

下面测试复合查询 bool

    /**
* 复合查询
* @return
* @throws IOException
*/
public static RestHighLevelClient boolSearch() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
SearchRequest request = new SearchRequest("users");
request.source(new SearchSourceBuilder()
.query(QueryBuilders.boolQuery()
.must(QueryBuilders.rangeQuery("age").gt(20))
.mustNot(QueryBuilders.termQuery("username","孙大圣"))
)
.from(0)
.size(5)
.sort("age", SortOrder.ASC)
);
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
System.out.println("Hits:" + search.getHits().totalHits);
search.getHits().forEach(e -> {
System.out.println(e.getSourceAsString());
});
return client;
}

结果:

Hits:
{"username":"奥斯特洛夫斯基","address":"光谷二路225号食堂","age":30}

下面测试地理查询

--矩形

    public static RestHighLevelClient geoSearch() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
SearchRequest request = new SearchRequest("china_index");
request.source(new SearchSourceBuilder()
// 地理边界查询,设置字段名,top Left和bottom Right
.query(QueryBuilders.geoBoundingBoxQuery("location").setCorners(23.1706638271,113.0383300781,22.9760953044,113.5025024414))
.from(0)
.size(100)
);
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
System.out.println("Hits:" + search.getHits().totalHits);
search.getHits().forEach(e -> {
System.out.println(e.getSourceAsString());
});
return client;
}

结果:

Hits:
{"pName":"广东省","cName":"广州","location":{"lat":23.12908,"lon":113.26436}}
{"pName":"广东省","cName":"越秀","location":{"lat":23.12901,"lon":113.2668}}
{"pName":"广东省","cName":"荔湾","location":{"lat":23.12586,"lon":113.24428}}
{"pName":"广东省","cName":"海珠","location":{"lat":23.08331,"lon":113.3172}}
{"pName":"广东省","cName":"天河","location":{"lat":23.12463,"lon":113.36199}}
{"pName":"广东省","cName":"白云","location":{"lat":23.157032,"lon":113.273238}}
{"pName":"广东省","cName":"佛山","location":{"lat":23.02185,"lon":113.12192}}
{"pName":"广东省","cName":"禅城","location":{"lat":23.00944,"lon":113.12249}}
{"pName":"广东省","cName":"南海","location":{"lat":23.02882,"lon":113.14278}}

--圆形

    public static RestHighLevelClient geoSearch() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
SearchRequest request = new SearchRequest("china_index");
List<GeoPoint> list = new ArrayList<>();
list.add(new GeoPoint(20.4270128143,110.2807617188));
list.add(new GeoPoint(19.6632802200,109.7094726563));
list.add(new GeoPoint(19.6839702359,110.8520507813));
request.source(new SearchSourceBuilder()
// 地理半径查询,设置字段名,纬度,经度,距离,距离类型
.query(QueryBuilders.geoDistanceQuery("location").point(39.6733703918,116.4111328125).distance(50, DistanceUnit.KILOMETERS))
.from(0)
.size(100)
);
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
System.out.println("Hits:" + search.getHits().totalHits);
search.getHits().forEach(e -> {
System.out.println(e.getSourceAsString());
});
return client;
}

结果:

Hits:
{"pName":"北京市","cName":"东城区","location":{"lat":39.92855,"lon":116.41637}}
{"pName":"北京市","cName":"西城区","location":{"lat":39.91231,"lon":116.36611}}
{"pName":"北京市","cName":"朝阳区","location":{"lat":39.927289,"lon":116.4498}}
{"pName":"北京市","cName":"丰台区","location":{"lat":39.85856,"lon":116.28616}}
{"pName":"北京市","cName":"石景山区","location":{"lat":39.90569,"lon":116.22299}}
{"pName":"北京市","cName":"海淀区","location":{"lat":39.95933,"lon":116.29845}}
{"pName":"北京市","cName":"通州区","location":{"lat":39.916195,"lon":116.662852}}
{"pName":"北京市","cName":"大兴区","location":{"lat":39.72684,"lon":116.34159}}
{"pName":"北京市","cName":"房山区","location":{"lat":39.74788,"lon":116.14294}}
{"pName":"北京市","cName":"门头沟区","location":{"lat":39.94048,"lon":116.10146}}
{"pName":"河北省","cName":"涿县","location":{"lat":39.48,"lon":115.98}}
{"pName":"河北省","cName":"廊坊","location":{"lat":39.53,"lon":116.7}}
{"pName":"河北省","cName":"安次","location":{"lat":39.52,"lon":116.69}}
{"pName":"河北省","cName":"固安","location":{"lat":39.44,"lon":116.29}}
{"pName":"河北省","cName":"永清","location":{"lat":39.32,"lon":116.48}}

--多边形

    public static RestHighLevelClient geoSearch() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
SearchRequest request = new SearchRequest("china_index");
List<GeoPoint> list = new ArrayList<>();
list.add(new GeoPoint(20.4270128143,110.2807617188));
list.add(new GeoPoint(19.6632802200,109.7094726563));
list.add(new GeoPoint(19.6839702359,110.8520507813));
request.source(new SearchSourceBuilder()
// 地理形状查询,设置字段名,围成多边形状的坐标列表
.query(QueryBuilders.geoPolygonQuery("location", list))
.from(0)
.size(100)
);
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
System.out.println("Hits:" + search.getHits().totalHits);
search.getHits().forEach(e -> {
System.out.println(e.getSourceAsString());
});
return client;
}

结果:

Hits:
{"pName":"海南省","cName":"海口","location":{"lat":20.02,"lon":110.35}}
{"pName":"海南省","cName":"琼山","location":{"lat":19.98,"lon":110.33}}
{"pName":"海南省","cName":"定安","location":{"lat":19.68,"lon":110.31}}
{"pName":"海南省","cName":"澄迈","location":{"lat":19.75,"lon":110.0}}

-- geo_shape查询

    /**
* 地理形状查询
* https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-shape.html
* 已知Builder实现:CircleBuilder, EnvelopeBuilder, GeometryCollectionBuilder, LineStringBuilder, MultiLineStringBuilder, MultiPointBuilder, MultiPolygonBuilder, PointBuilder, PolygonBuilder
* @return
* @throws IOException
*/
public static RestHighLevelClient geoShapeSearch() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
SearchRequest request = new SearchRequest("china_shape_index");
request.source(new SearchSourceBuilder()
.query(QueryBuilders.geoShapeQuery("location",
// 查询类型为envelope就用EnvelopeBuilder. topLeft,bottomRight. new Coordinate(经度,纬度)
new EnvelopeBuilder(new Coordinate(114.9169921875,40.5137991550),new Coordinate(118.6083984375,38.7883453551)))
.relation(ShapeRelation.INTERSECTS)
)
// ShapeBuilders已经过时,不推荐使用了
//.query(QueryBuilders.geoShapeQuery("location",ShapeBuilders.newEnvelope(new Coordinate(114.9169921875,40.5137991550),new Coordinate(118.6083984375,38.7883453551))))
.from(0)
.size(100)
);
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
System.out.println("Hits:" + search.getHits().totalHits);
search.getHits().forEach(e -> {
System.out.println(e.getSourceAsString());
});
return client;
}

结果:

Hits:
{"location":{"type":"circle","coordinates":[116.54296875,39.7071866568],"radius":"10km"}}

12. Search

**search scroll

    /**
* scrollSearch
* @return
* @throws IOException
*/
public static RestHighLevelClient scrollSearch() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
// 设置超时
final Scroll scroll = new Scroll(TimeValue.timeValueMinutes(1L));
SearchRequest request = new SearchRequest("books");
request.source(new SearchSourceBuilder()
.query(QueryBuilders.matchAllQuery())
.sort("_id",SortOrder.ASC)
.size(500)) // 每批大小
.scroll(scroll); // 设置scroll
SearchResponse searchResponse = client.search(request, RequestOptions.DEFAULT); // 执行查询
String scrollId = searchResponse.getScrollId();
SearchHit[] hits = searchResponse.getHits().getHits();
while(hits != null && hits.length > 0) {
System.out.println("========Begin=======");
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
System.out.println("========End======="); System.out.println("Size:" + hits.length + ",Scroll:" + scrollId);
SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId)
.scroll(scroll); // 设置SearchScrollRequest
searchResponse = client.scroll(scrollRequest, RequestOptions.DEFAULT); // 拉取新的数据
scrollId = searchResponse.getScrollId();
hits = searchResponse.getHits().getHits();
};
// 当scroll超时时,Search Scroll API使用的搜索上下文将自动删除
ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
clearScrollRequest.addScrollId(scrollId);
ClearScrollResponse clearScrollResponse = client.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
boolean succeeded = clearScrollResponse.isSucceeded();
System.out.println("ClearScroll:" + succeeded);
return client;
}

结果:【一共2000条,省略了部分结果】

========Begin=======
{"title":"title_1","user":"user_1"}
{"title":"title_10","user":"user_10"}
{"title":"title_100","user":"user_100"}
{"title":"title_1000","user":"user_1000"}
...
{"title":"title_1448","user":"user_1448"}
========End=======
Size:,Scroll:DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAM7QFndDcjZVejBqVHZHYVRIaDVhY054S0EAAAAAAADOzxZ3Q3I2VXowalR2R2FUSGg1YWNOeEtBAAAAAAAAztEWd0NyNlV6MGpUdkdhVEhoNWFjTnhLQQAAAAAAAM7SFndDcjZVejBqVHZHYVRIaDVhY054S0EAAAAAAADO0xZ3Q3I2VXowalR2R2FUSGg1YWNOeEtB
========Begin=======
...
{"title":"title_1899","user":"user_1899"}
========End=======
Size:,Scroll:DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAM7QFndDcjZVejBqVHZHYVRIaDVhY054S0EAAAAAAADOzxZ3Q3I2VXowalR2R2FUSGg1YWNOeEtBAAAAAAAAztEWd0NyNlV6MGpUdkdhVEhoNWFjTnhLQQAAAAAAAM7SFndDcjZVejBqVHZHYVRIaDVhY054S0EAAAAAAADO0xZ3Q3I2VXowalR2R2FUSGg1YWNOeEtB
========Begin=======
{"title":"title_19","user":"user_19"}
...
{"title":"title_548","user":"user_548"}
========End=======
Size:,Scroll:DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAM7QFndDcjZVejBqVHZHYVRIaDVhY054S0EAAAAAAADOzxZ3Q3I2VXowalR2R2FUSGg1YWNOeEtBAAAAAAAAztEWd0NyNlV6MGpUdkdhVEhoNWFjTnhLQQAAAAAAAM7SFndDcjZVejBqVHZHYVRIaDVhY054S0EAAAAAAADO0xZ3Q3I2VXowalR2R2FUSGg1YWNOeEtB
========Begin=======
{"title":"title_549","user":"user_549"}
...
{"title":"title_6","user":"user_6"}
{"title":"title_60","user":"user_60"}
{"title":"title_600","user":"user_600"}
...
{"title":"title_699","user":"user_699"}
{"title":"title_7","user":"user_7"}
{"title":"title_70","user":"user_70"}
{"title":"title_700","user":"user_700"}
...
{"title":"title_799","user":"user_799"}
{"title":"title_8","user":"user_8"}
{"title":"title_80","user":"user_80"}
{"title":"title_800","user":"user_800"}
...
{"title":"title_899","user":"user_899"}
{"title":"title_9","user":"user_9"}
{"title":"title_90","user":"user_90"}
{"title":"title_900","user":"user_900"}
...
{"title":"title_999","user":"user_999"}
========End=======
Size:,Scroll:DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAM7QFndDcjZVejBqVHZHYVRIaDVhY054S0EAAAAAAADOzxZ3Q3I2VXowalR2R2FUSGg1YWNOeEtBAAAAAAAAztEWd0NyNlV6MGpUdkdhVEhoNWFjTnhLQQAAAAAAAM7SFndDcjZVejBqVHZHYVRIaDVhY054S0EAAAAAAADO0xZ3Q3I2VXowalR2R2FUSGg1YWNOeEtB
ClearScroll:true

**Multi-Search

HTTP请求

# 格式:一行header一行body
GET users/_msearch
{}
{"query": {"terms" : { "username" : ["孙行者", "孙大圣"]}}}
{}
{"query": {"term" : { "username" : "Brfxxccxxmnpcccclllmmnprxvclmnckssqlbb1111b"}}}
---
{
"responses" : [
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 2,
"max_score" : 1.0,
"hits" : [
{
"_index" : "users",
"_type" : "info",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"username" : "孙行者",
"address" : "软件产业基地1栋B座大堂",
"age" : 15
}
},
{
"_index" : "users",
"_type" : "info",
"_id" : "2",
"_score" : 1.0,
"_source" : {
"username" : "孙大圣",
"address" : "万达北路710号戈雅公寓105号商铺",
"age" : 26
}
}
]
},
"status" :
},
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 1.3862944,
"hits" : [
{
"_index" : "users",
"_type" : "info",
"_id" : "5",
"_score" : 1.3862944,
"_source" : {
"username" : "Brfxxccxxmnpcccclllmmnprxvclmnckssqlbb1111b",
"address" : "海淀紫竹院路甲2号商业05号",
"age" : 18
}
}
]
},
"status" :
}
]
}

Java

public static RestHighLevelClient multiSearch() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
MultiSearchRequest request = new MultiSearchRequest();
// 第一个查询
SearchRequest firstSearchRequest = new SearchRequest("users");
firstSearchRequest.source(new SearchSourceBuilder().query(QueryBuilders.termsQuery("username","孙大圣")));
request.add(firstSearchRequest);
// 第二个查询
SearchRequest secondSearchRequest = new SearchRequest("users");
secondSearchRequest.source(new SearchSourceBuilder().query(QueryBuilders.prefixQuery("username", "Brfxx")));
request.add(secondSearchRequest); MultiSearchResponse msearch = client.msearch(request, RequestOptions.DEFAULT);
MultiSearchResponse.Item[] responses = msearch.getResponses();
for (MultiSearchResponse.Item i : responses){
System.out.println("========" + i.getResponse().status().name());
i.getResponse().getHits().forEach(e -> {
System.out.println(e.getSourceAsString());
});
}
return client;
}

结果:

========OK
{"username":"孙大圣","address":"万达北路710号戈雅公寓105号商铺","age":26}
========OK
{"username":"Brfxxccxxmnpcccclllmmnprxvclmnckssqlbb1111b","address":"海淀紫竹院路甲2号商业05号","age":18}

13. Cluster

HTTP请求

GET _cluster/health
---
{
"cluster_name" : "my-elasticsearch",
"status" : "yellow",
"timed_out" : false,
"number_of_nodes" : 1,
"number_of_data_nodes" : 1,
"active_primary_shards" : 15,
"active_shards" : 15,
"relocating_shards" : 0,
"initializing_shards" : 0,
"unassigned_shards" : 14,
"delayed_unassigned_shards" : 0,
"number_of_pending_tasks" : 0,
"number_of_in_flight_fetch" : 0,
"task_max_waiting_in_queue_millis" : 0,
"active_shards_percent_as_number" : 51.724137931034484
}

获取集群状态

GET /_cluster/state
---
{
"cluster_name" : "my-elasticsearch",
"compressed_size_in_bytes" : 14766,
"cluster_uuid" : "QmDZ773JR_ip0AN6jEdWtA",
"version" : 33,
"state_uuid" : "l8WJu9BzTfGsIKba_gsodA",
"master_node" : "wCr6Uz0jTvGaTHh5acNxKA",
"blocks" : { },
"nodes" : {
"wCr6Uz0jTvGaTHh5acNxKA" : {
"name" : "wCr6Uz0",
"ephemeral_id" : "qFZoP0iWQDm3EWM3TDb_vg",
"transport_address" : "127.0.0.1:9300",
"attributes" : {
"ml.machine_memory" : "8510087168",
"xpack.installed" : "true",
"ml.max_open_jobs" : "20",
"ml.enabled" : "true"
}
}
},
...
}
GET /_cluster/stats?human&pretty

GET /_cluster/settings

# 设置集群settings
# . transient cluster settings
# . persistent cluster settings
# . settings in the elasticsearch.yml configuration file.
PUT /_cluster/settings
{
"persistent" : {
"indices.recovery.max_bytes_per_sec" : "50mb"
}
} # explain索引【三个参数必须的】
GET /_cluster/allocation/explain
{
"index": "china_index",
"shard": 0,
"primary": true
} # 节点统计数据
GET /_nodes/stats
GET /_nodes/nodeId1,nodeId2/stats # return just indices
GET /_nodes/stats/indices # return just os and process
GET /_nodes/stats/os,process # return just process for node with IP address 10.0.0.1
GET /_nodes/10.0.0.1/stats/process # 每个节点的实用信息
GET _nodes/usage
GET _nodes/nodeId1,nodeId2/usage

Java

    /**
* 集群信息
* @return
*/
public static RestHighLevelClient info() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
boolean ping = client.ping(RequestOptions.DEFAULT);
System.out.println("Ping:" + ping);
MainResponse info = client.info(RequestOptions.DEFAULT);
ClusterName clusterName = info.getClusterName();
String clusterUuid = info.getClusterUuid();
String nodeName = info.getNodeName();
Version version = info.getVersion();
Build build = info.getBuild();
System.out.println("集群名称:" + clusterName.value());
System.out.println("Uuid:" + clusterUuid);
System.out.println("节点名称:" + nodeName);
System.out.println("Version:" + version.toString());
System.out.println("Bulid:" + build.toString());
return client;
}

结果:

Ping:true
集群名称:my-elasticsearch
Uuid:QmDZ773JR_ip0AN6jEdWtA
节点名称:wCr6Uz0
Version:6.5.
Bulid:[default][zip][816e6f6][--09T18::.352602Z]

14. Indices

14.1 分词器

# 标准分词器
GET _analyze
{
"analyzer" : "standard",
"text" : ["this is a test", "the second text"]
}
# IK分词器
GET _analyze
{
"analyzer" : "ik_smart",
"text" : ["真好玩", "一个叫yado的博士找到他,希望buzzo和他的团伙去帮他散布一种叫做joy的毒品"]
}

--

    /**
* 分词器
* @return
* @throws IOException
*/
public static RestHighLevelClient analyze() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
AnalyzeRequest request = new AnalyzeRequest();
request.text("真好玩", "一个叫yado的博士找到他,希望buzzo和他的团伙去帮他散布一种叫做joy的毒品");
request.analyzer("ik_smart");
AnalyzeResponse response = client.indices().analyze(request, RequestOptions.DEFAULT);
List<AnalyzeResponse.AnalyzeToken> tokens = response.getTokens(); for(AnalyzeResponse.AnalyzeToken t : tokens){
int endOffset = t.getEndOffset();
int position = t.getPosition();
int positionLength = t.getPositionLength();
int startOffset = t.getStartOffset();
String term = t.getTerm();
String type = t.getType();
System.out.println("Start:" + startOffset + ",End:" + endOffset + ",Position:" + position + ",Length:" + positionLength +
",Term:" + term + ",Type:" + type);
}
return client;
}

结果:

Start:,End:,Position:,Length:,Term:真好玩,Type:CN_WORD
Start:,End:,Position:,Length:,Term:一个,Type:CN_WORD
Start:,End:,Position:,Length:,Term:叫,Type:CN_CHAR
Start:,End:,Position:,Length:,Term:yado,Type:ENGLISH
Start:,End:,Position:,Length:,Term:的,Type:CN_CHAR
Start:,End:,Position:,Length:,Term:博士,Type:CN_WORD
Start:,End:,Position:,Length:,Term:找,Type:CN_CHAR
Start:,End:,Position:,Length:,Term:到他,Type:CN_WORD
Start:,End:,Position:,Length:,Term:希望,Type:CN_WORD
Start:,End:,Position:,Length:,Term:buzzo,Type:ENGLISH
Start:,End:,Position:,Length:,Term:和他,Type:CN_WORD
Start:,End:,Position:,Length:,Term:的,Type:CN_CHAR
Start:,End:,Position:,Length:,Term:团伙,Type:CN_WORD
Start:,End:,Position:,Length:,Term:去,Type:CN_CHAR
Start:,End:,Position:,Length:,Term:帮,Type:CN_CHAR
Start:,End:,Position:,Length:,Term:他,Type:CN_CHAR
Start:,End:,Position:,Length:,Term:散布,Type:CN_WORD
Start:,End:,Position:,Length:,Term:一种,Type:CN_WORD
Start:,End:,Position:,Length:,Term:叫做,Type:CN_WORD
Start:,End:,Position:,Length:,Term:joy,Type:ENGLISH
Start:,End:,Position:,Length:,Term:的,Type:CN_CHAR
Start:,End:,Position:,Length:,Term:毒品,Type:CN_WORD

14.2 Create Index

创建索引限制

小写字母

不能包含 \, /, *, ?, ", <, >, |, ` ` (space character), ,, #

7.0之前的索引可能包含冒号(:),但是不赞成这样做,7.0+不支持这样做

不能以-,_,+开头

不能. or ..

长度不能超过255字节

HTTP请求

# 创建索引
PUT twitter
{
"settings" : {
"number_of_shards" : 3,
"number_of_replicas" : 2
},
"mappings" : {
"my_doc" : {
"properties" : {
"field1" : { "type" : "text" }
}
}
}
}

Java

    public static RestHighLevelClient createIndex() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
CreateIndexRequest request = new CreateIndexRequest("twitter");
request.settings(Settings.builder()
.put("index.number_of_shards", 3)
.put("index.number_of_replicas", 2))
// 设置mapping
//.mapping("t_doc", "field1","type=keyword,store=true") // Object key-pairs
.mapping("t_doc", jsonBuilder()
.startObject()
.startObject("t_doc")
.startObject("properties")
.startObject("msg")
.field("type","text")
.endObject()
.endObject()
.endObject()
.endObject())
// 别名
.alias(new Alias("my_index_alias"))
// 创建超时
.timeout(TimeValue.timeValueMinutes(2))
// 连接到主节点超时时间
.masterNodeTimeout(TimeValue.timeValueMinutes(1))
// 在创建索引返回响应之前等待的活动碎片副本的数量
.waitForActiveShards(2);
CreateIndexResponse indexResponse = client.indices().create(request, RequestOptions.DEFAULT);
boolean acknowledged = indexResponse.isAcknowledged();
boolean shardsAcknowledged = indexResponse.isShardsAcknowledged();
System.out.println(acknowledged);
return client;
}

14.3 Delete Index

# 删除索引
DELETE /twitter

Java

    public static RestHighLevelClient deleteIndex() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
DeleteIndexRequest request = new DeleteIndexRequest();
// 使用_all或者通配符*可以删除所有索引。如果要禁用:action.destructive_requires_name=true
request.indices("twitter","it_book","car","school","story"); try {
AcknowledgedResponse acknowledgedResponse = client.indices().delete(request, RequestOptions.DEFAULT);
boolean acknowledged = acknowledgedResponse.isAcknowledged();
System.out.println(acknowledged);
} catch (ElasticsearchException exception) {
if (exception.status() == RestStatus.NOT_FOUND) {
System.err.println("Index Not Found");
}
}
return client;
}

14.4 Indices Exists

# 索引是否存在
HEAD /china_index
# Type是否存在
HEAD /china_index/_mapping/city

Java

    public static RestHighLevelClient existIndex() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
GetIndexRequest request = new GetIndexRequest();
request.indices("china_index");
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
System.out.println(exists);
return client;
}

14.5 Open Index

# 开启索引
POST /twitter/_open

Java

    public static RestHighLevelClient openIndex() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
OpenIndexRequest request = new OpenIndexRequest("twitter");
request.timeout(TimeValue.timeValueMinutes(2));
OpenIndexResponse open = client.indices().open(request, RequestOptions.DEFAULT);
boolean acknowledged = open.isAcknowledged();
boolean shardsAcked = open.isShardsAcknowledged();
System.out.println(acknowledged);
return client;
}

14.6 Close Index

# 关闭索引
POST /twitter/_close

Java

    public static RestHighLevelClient closeIndex() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
CloseIndexRequest request = new CloseIndexRequest("twitter");
request.timeout(TimeValue.timeValueMinutes(2));
AcknowledgedResponse closeIndexResponse = client.indices().close(request, RequestOptions.DEFAULT);
boolean acknowledged = closeIndexResponse.isAcknowledged();
System.out.println(acknowledged);
return client;
}

14.7 Shrink Index【压缩索引】

# 准备源索引
PUT my_source_index
{
"settings" : {
"number_of_shards" : 4,
"number_of_replicas" : 2,
"index.blocks.write": true
}
}
--
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "my_source_index"
}

压缩操作

POST my_source_index/_shrink/my_target_index?copy_settings=true
{
"settings": {
"index.number_of_shards": 1,
"index.number_of_replicas": 1,
"index.codec": "best_compression"
},
"aliases": {
"my_search_indices": {}
}
}
--
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "my_target_index"
}

查看索引信息

GET my_source_index
结果:
{
"my_source_index" : {
"aliases" : { },
"mappings" : { },
"settings" : {
"index" : {
"number_of_shards" : "4",
"blocks" : {
"write" : "true"
},
"provided_name" : "my_source_index",
"creation_date" : "",
"number_of_replicas" : "",
"uuid" : "tSYNLldWQNCOlR5NJGaH9g",
"version" : {
"created" : "6050099"
}
}
}
}
}
---
GET my_target_index
结果:
{
"my_target_index" : {
"aliases" : {
"my_search_indices" : { }
},
"mappings" : { },
"settings" : {
"index" : {
"allocation" : {
"max_retries" : "1"
},
"shrink" : {
"source" : {
"name" : "my_source_index",
"uuid" : "tSYNLldWQNCOlR5NJGaH9g"
}
},
"blocks" : {
"write" : "true"
},
"provided_name" : "my_target_index",
"creation_date" : "",
"number_of_replicas" : "",
"uuid" : "F976xviGQ965JU9patwQnA",
"version" : {
"created" : "6050099",
"upgraded" : "6050099"
},
"codec" : "best_compression",
"routing" : {
"allocation" : {
"initial_recovery" : {
"_id" : "wCr6Uz0jTvGaTHh5acNxKA"
}
}
},
"number_of_shards" : "",
"routing_partition_size" : "",
"resize" : {
"source" : {
"name" : "my_source_index",
"uuid" : "tSYNLldWQNCOlR5NJGaH9g"
}
}
}
}
}
}

Java

    /**
* 压缩索引(将索引压缩为主分片数更少的新索引)
* 目标索引中请求的主碎片数量必须是源索引中碎片数量的一个因数。例如,有8个主碎片的索引可以压缩为4个、2个或1个主碎片;
* 或者有15个主碎片的索引可以压缩为5个、3个或1个主碎片。
* 过程:
* 首先,它创建一个新的目标索引,其定义与源索引相同,但是主碎片的数量较少
* 然后它将段从源索引硬链接到目标索引
* 最后,它将目标索引恢复为一个刚刚重新打开的closed index
* @return
*/
public static RestHighLevelClient shrinkIndex() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
ResizeRequest resizeRequest = new ResizeRequest("target_index", "source_index");
resizeRequest.getTargetIndexRequest()
.alias(new Alias("target_index_alias"))
.settings(Settings.builder()
.put("index.number_of_shards", 2)
);
ResizeResponse resizeResponse = client.indices().shrink(resizeRequest, RequestOptions.DEFAULT);
boolean acknowledged = resizeResponse.isAcknowledged();
boolean shardsAcked = resizeResponse.isShardsAcknowledged();
System.out.println(acknowledged);
return client;
}

14.8 Split Index

准备数据

# index.number_of_routing_shards must be >= index.number_of_shards
PUT my_source_index2
{
"settings" : {
"number_of_shards" : 2,
"index.number_of_routing_shards" : 8,
"index.blocks.write": true
}
}
--
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "my_source_index2"
}

拆分

# 拆分索引
POST my_source_index2/_split/my_target_index2?copy_settings=true
{
"settings": {
"index.number_of_shards": 4
},
"aliases": {
"my_search_indices": {}
}
}
--
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "my_target_index2"
}

查看索引

GET my_source_index2
结果:
{
"my_source_index2" : {
"aliases" : { },
"mappings" : { },
"settings" : {
"index" : {
"number_of_shards" : "2",
"blocks" : {
"write" : "true"
},
"provided_name" : "my_source_index2",
"creation_date" : "",
"number_of_replicas" : "",
"uuid" : "iuDENl3uQku0Ef6flu8S-Q",
"version" : {
"created" : "6050099"
}
}
}
}
}
---
GET my_target_index2
结果:
{
"my_target_index2" : {
"aliases" : {
"my_search_indices" : { }
},
"mappings" : { },
"settings" : {
"index" : {
"number_of_shards" : "4",
"routing_partition_size" : "1",
"blocks" : {
"write" : "true"
},
"provided_name" : "my_target_index2",
"resize" : {
"source" : {
"name" : "my_source_index2",
"uuid" : "iuDENl3uQku0Ef6flu8S-Q"
}
},
"creation_date" : "",
"number_of_replicas" : "",
"uuid" : "ZBnocs2bSker45kb2lXoRw",
"version" : {
"created" : "6050099",
"upgraded" : "6050099"
}
}
}
}
}

Java

    /**
* 拆分索引(每个原始的主碎片被拆分为新索引中的两个或多个主碎片)
* 重要:源索引必须在创建的时候指定number_of_routing_shards参数,以便将来有拆分的需要。在Elasticsearch 7.0这个前提被移除。
* 索引能被拆分的次数以及每个主分片能被拆分的个数取决于index.number_of_routing_shards参数的设置
* 过程:
* 首先,它创建一个新的目标索引,其定义与源索引相同,但是具有更多的主碎片
* 然后它将段从源索引硬链接到目标索引
* 创建了低级文件之后,所有文档将再次散列以删除属于不同碎片的文档
* 最后,它将目标索引恢复为一个刚刚重新打开的closed index
* @return
*/
public static RestHighLevelClient splitIndex() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
ResizeRequest resizeRequest = new ResizeRequest("target_index", "source_index");
resizeRequest.timeout(TimeValue.timeValueSeconds(2))
.masterNodeTimeout(TimeValue.timeValueMinutes(1))
.setResizeType(ResizeType.SPLIT); // 类型是拆分
resizeRequest.getTargetIndexRequest()
.alias(new Alias("target_index_alias"))
.settings(Settings.builder()
.put("index.number_of_shards", 4));
ResizeResponse resizeResponse = client.indices().split(resizeRequest, RequestOptions.DEFAULT);
boolean acknowledged = resizeResponse.isAcknowledged();
boolean shardsAcked = resizeResponse.isShardsAcknowledged();
return client;
}

14.9 Refresh

# 刷新索引【默认定期刷新】
POST /kimchy,elasticsearch/_refresh
POST /_refresh

--

    /**
* 刷新索引
* 默认情况下,刷新是定期调度的
* @return
*/
public static RestHighLevelClient refreshIndex() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
RefreshRequest refreshRequest = new RefreshRequest("index_1","index_2"); try {
RefreshResponse refresh = client.indices().refresh(refreshRequest, RequestOptions.DEFAULT);
int totalShards = refresh.getTotalShards();
int successfulShards = refresh.getSuccessfulShards();
int failedShards = refresh.getFailedShards();
DefaultShardOperationFailedException[] failures = refresh.getShardFailures();
} catch (ElasticsearchException exception) {
if (exception.status() == RestStatus.NOT_FOUND) {
// TODO
}
}
return client;
}

14.10 Flush

POST twitter/_flush

---

    /**
* https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-flush.html
* 索引的刷新进程通过将数据刷新到索引存储并清除内部事务日志,基本上将内存从索引中释放出来
* @return
* @throws IOException
*/
public static RestHighLevelClient flushIndex() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
FlushRequest requestMultiple = new FlushRequest("index1", "index2");
try {
FlushResponse flushResponse = client.indices().flush(requestMultiple, RequestOptions.DEFAULT);
int totalShards = flushResponse.getTotalShards();
int successfulShards = flushResponse.getSuccessfulShards();
int failedShards = flushResponse.getFailedShards();
DefaultShardOperationFailedException[] failures = flushResponse.getShardFailures();
} catch (ElasticsearchException exception) {
if (exception.status() == RestStatus.NOT_FOUND) {
// TODO
}
}
return client;
}

14.11 Clear Cache

# 清空缓存
POST /twitter/_cache/clear

---

    /**
* 清除索引的缓存
* @return
*/
public static RestHighLevelClient clearCacheIndex() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
ClearIndicesCacheRequest cacheRequest = new ClearIndicesCacheRequest("index1", "index2");
cacheRequest.queryCache(true); // 查询
cacheRequest.fieldDataCache(true); // 字段数据
cacheRequest.requestCache(true); // 请求
cacheRequest.fields("field1", "field2", "field3"); try {
ClearIndicesCacheResponse clearCache = client.indices().clearCache(cacheRequest, RequestOptions.DEFAULT);
int totalShards = clearCache.getTotalShards();
int successfulShards = clearCache.getSuccessfulShards();
int failedShards = clearCache.getFailedShards();
DefaultShardOperationFailedException[] failures = clearCache.getShardFailures();
} catch (ElasticsearchException exception) {
if (exception.status() == RestStatus.NOT_FOUND) {
// TODO
}
}
return client;
}

14.12 Force Merge 

Http

# 合并
POST /kimchy/_forcemerge?only_expunge_deletes=false&max_num_segments=&flush=true
# max_num_segments=,所有的段都重写为一个新的
POST /kimchy,elasticsearch/_forcemerge

Java

    /**
* 合并一个或多个索引
* 此调用将阻塞,直到合并完成。如果http连接丢失,请求将在后台继续,任何新请求都将阻塞,直到前一个强制合并完成
* **强制合并只能对只读索引调用。对读写索引执行强制合并会导致产生非常大的段(每段大于5GB)
* https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-force-merge.html
* https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html
* @return
*/
public static RestHighLevelClient ForceMergeIndex() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
ForceMergeRequest requestMultiple = new ForceMergeRequest("index1", "index2");
// 要合并的分片数。要完全合并索引,请将其设置为1
requestMultiple.maxNumSegments(1);
// 合并过程是否删除标记为删除的段。在Lucene中,一个文档不是从一个段中删除,而是标记为已删除。在段的合并过程中,将创建一个没有这些删除的新段。
// 此标志只允许合并具有删除的段。默认值为false
requestMultiple.onlyExpungeDeletes(true);
requestMultiple.flush(true); try {
ForceMergeResponse forceMergeResponse = client.indices().forcemerge(requestMultiple, RequestOptions.DEFAULT);
int totalShards = forceMergeResponse.getTotalShards();
int successfulShards = forceMergeResponse.getSuccessfulShards();
int failedShards = forceMergeResponse.getFailedShards();
DefaultShardOperationFailedException[] failures = forceMergeResponse.getShardFailures();
} catch (ElasticsearchException exception) {
if (exception.status() == RestStatus.NOT_FOUND) {
// TODO
}
}
return client;
}

14.13 Put Mapping

HTTP

# 增加一个不带type的索引
PUT twitter
{}
# 增加type
PUT twitter/_mapping/_doc
{
"properties": {
"email": {
"type": "keyword"
}
}
}

Java

    /**
* 添加mapping(不能更新已存在的字段类型)
* @return
*/
public static RestHighLevelClient putMapping() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
PutMappingRequest request = new PutMappingRequest("twitter");
request.type("_doc");
// 我更喜欢Object key-pairs 的形式
request.source("message","type=text","name","type=keyword");
request.timeout(TimeValue.timeValueMinutes(2));
request.masterNodeTimeout(TimeValue.timeValueMinutes(1));
AcknowledgedResponse putMappingResponse = client.indices().putMapping(request, RequestOptions.DEFAULT);
boolean acknowledged = putMappingResponse.isAcknowledged();
System.out.println(acknowledged);
return client;
}

14.14 Get Mappings

HTTP

# 获取全部索引的Mapping,可以精确到type
GET /_all/_mapping/[Type]
#获取指定索引的Mapping
GET /twitter/_mapping/[Type]
# 例如:
GET /china_index/_mapping
...
{
"china_index" : {
"mappings" : {
"city" : {
"properties" : {
"cName" : {
"type" : "text"
},
"location" : {
"type" : "geo_point"
},
"pName" : {
"type" : "keyword"
}
}
}
}
}
}

Java

    /**
* 获取mapping
* @return
* @throws IOException
*/
public static RestHighLevelClient getMapping() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
GetMappingsRequest request = new GetMappingsRequest();
request.indices("china_index");
request.types("city");
request.masterNodeTimeout(TimeValue.timeValueMinutes(1));
GetMappingsResponse getMappingResponse = client.indices().getMapping(request, RequestOptions.DEFAULT);
getMappingResponse.getMappings().forEach(e -> {
String key = e.key;
ImmutableOpenMap<String, MappingMetaData> value = e.value;
value.forEach(v -> {
System.out.println(key + "|" + v.key + "|" + v.value.getSourceAsMap());
});
});
return client;
}

结果:

china_index|city|{properties={pName={type=keyword}, cName={type=text}, location={type=geo_point}}}

14.15 Get Field Mappings

HTTP

# 查看具体字段的Mapping信息
GET [索引]/_mapping/field/[field1,field2]
GET china_index/_mapping/field/pName,location
..
{
"china_index" : {
"mappings" : {
"city" : {
"pName" : {
"full_name" : "pName",
"mapping" : {
"pName" : {
"type" : "keyword"
}
}
},
"location" : {
"full_name" : "location",
"mapping" : {
"location" : {
"type" : "geo_point"
}
}
}
}
}
}
}

Java

    /**
* 获取指定字段的Mapping
* @return
* @throws IOException
*/
public static RestHighLevelClient getFieldMappings() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
GetFieldMappingsRequest request = new GetFieldMappingsRequest();
request.indices("china_index"); // 可以多个索引
request.types("city"); // 多个类型
request.fields("pName","location"); // 多个字段
GetFieldMappingsResponse response = client.indices().getFieldMapping(request, RequestOptions.DEFAULT);
Map<String, Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetaData>>> mappings = response.mappings();
mappings.keySet().forEach(e -> {
Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetaData>> mapMap = mappings.get(e);
mapMap.keySet().forEach(i -> {
Map<String, GetFieldMappingsResponse.FieldMappingMetaData> metaDataMap = mapMap.get(i);
metaDataMap.keySet().forEach(j -> {
GetFieldMappingsResponse.FieldMappingMetaData fieldMappingMetaData = metaDataMap.get(j);
System.out.println(e + "|" + i + "|" + j + "|" + fieldMappingMetaData.sourceAsMap());
});
});
});
return client;
}

结果:

china_index|city|pName|{pName={type=keyword}}
china_index|city|location|{location={type=geo_point}}

14.16 Index Aliases

HTTP

# 添加别名
POST /_aliases
{
"actions" : [
{ "remove" : { "index" : "test1", "alias" : "alias1" } },
{ "add" : { "index" : "test2", "alias" : "alias1" } }
]
}
# 例子
POST /_aliases
{
"actions" : [
{ "add" : { "index" : "my_source_index", "alias" : "alias111" } },
{ "add" : { "index" : "my_source_index2", "alias" : "alias222" } }
]
}
...
{
"acknowledged" : true
}

Java

    /**
* 添加别名,这个方法只是列出了一些情况,如果要运行请先根据实际情况修改
* @return
*/
public static RestHighLevelClient indexAlias() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
IndicesAliasesRequest request = new IndicesAliasesRequest();
IndicesAliasesRequest.AliasActions aliasAction =
new IndicesAliasesRequest.AliasActions(IndicesAliasesRequest.AliasActions.Type.ADD)
.index("index1")
.alias("alias1");
// 添加别名,并指定routing
IndicesAliasesRequest.AliasActions addIndicesAction =
new IndicesAliasesRequest.AliasActions(IndicesAliasesRequest.AliasActions.Type.ADD)
.indices("index1", "index2")
.alias("alias2")
.routing("my_routing");
// 移除别名
IndicesAliasesRequest.AliasActions removeAction =
new IndicesAliasesRequest.AliasActions(IndicesAliasesRequest.AliasActions.Type.REMOVE)
.index("index3")
.alias("alias3");
// 删除索引
IndicesAliasesRequest.AliasActions removeIndexAction =
new IndicesAliasesRequest.AliasActions(IndicesAliasesRequest.AliasActions.Type.REMOVE_INDEX)
.index("index4");
request.addAliasAction(aliasAction);
AcknowledgedResponse indicesAliasesResponse =
client.indices().updateAliases(request, RequestOptions.DEFAULT);
boolean acknowledged = indicesAliasesResponse.isAcknowledged();
System.out.println(acknowledged);
return client;
}

14.17 Exists Alias

HTTP

# 检查
HEAD /my_source_index/_alias/alias111
# 从所有索引里面找别名为2016的
HEAD /_alias/
# 还可以使用通配符
HEAD /_alias/*
---
存在的话
- OK
不存在
- Not Found

Java

    /**
* 判断别名是否存在
* @return
* @throws IOException
*/
public static RestHighLevelClient aliasExist() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
GetAliasesRequest request = new GetAliasesRequest();
request.aliases("alias222");
request.indices("my_source_index2");
// GetAliasesRequest requestWithAlias = new GetAliasesRequest("alias1"); // 单个
// GetAliasesRequest requestWithAliases =
// new GetAliasesRequest(new String[]{"alias1", "alias2"}); // 多个
boolean exists = client.indices().existsAlias(request, RequestOptions.DEFAULT);
System.out.println(exists);
return client;
}

结果:true

14.18 Get Alias

HTTP

# 获取
GET /my_source_index/_alias/alias111
--
{
"my_source_index" : {
"aliases" : {
"alias111" : { }
}
}
}
# 从所有索引里面找别名为alias222的
GET /_alias/alias222
--
{
"my_source_index2" : {
"aliases" : {
"alias222" : { }
}
}
}
# 还可以使用通配符
GET /_alias/*
# 显示索引的所有别名
GET /my_source_index/_alias/*
# 所有别名
GET /_alias/*
--
{
"my_target_index2" : {
"aliases" : {
"my_search_indices" : { }
}
},
"my_source_index2" : {
"aliases" : {
"alias222" : { }
}
},
".kibana_" : {
"aliases" : {
".kibana" : { }
}
},
"my_source_index" : {
"aliases" : {
"alias111" : { }
}
},
"my_target_index" : {
"aliases" : {
"my_search_indices" : { }
}
}
}

如果要删除

# 删除别名
DELETE /my_source_index/_alias/alias111
--
{
"acknowledged" : true
}

Java

    /**
* 获取别名
* @return
* @throws IOException
*/
public static RestHighLevelClient getAlias() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
GetAliasesRequest request = new GetAliasesRequest();
request.aliases("alias222");
request.indices("my_source_index2");
// GetAliasesRequest requestWithAlias = new GetAliasesRequest("alias1");
// GetAliasesRequest requestWithAliases =
// new GetAliasesRequest(new String[]{"alias1", "alias2"});
GetAliasesResponse response = client.indices().getAlias(request, RequestOptions.DEFAULT);
Map<String, Set<AliasMetaData>> aliases = response.getAliases();
aliases.keySet().forEach(e -> {
Set<AliasMetaData> aliasMetaData = aliases.get(e);
System.out.println(e + ":" + aliasMetaData.toString());
});
return client;
}

结果:

my_source_index2:[{
"alias222" : { }
}]

14.19 Update Indices Settings

HTTP

# 更新setting
PUT /twitter/_settings
{
"index" : {
"number_of_replicas" : 2,
"refresh_interval" : "1s"
}
}

Java

    /**
* 更新setting
* @return
* @throws IOException
*/
public static RestHighLevelClient updateSetting() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
// 更新单个
UpdateSettingsRequest request = new UpdateSettingsRequest("index1");
// 更新多个
//UpdateSettingsRequest requestMultiple =
// new UpdateSettingsRequest("index1", "index2");
// 全部更新
//UpdateSettingsRequest requestAll = new UpdateSettingsRequest();
Settings settings =
Settings.builder()
.put("index.number_of_replicas", 2)
.build();
request.settings(settings);
AcknowledgedResponse updateSettingsResponse =
client.indices().putSettings(request, RequestOptions.DEFAULT);
boolean acknowledged = updateSettingsResponse.isAcknowledged();
System.out.println(acknowledged);
return client;
}

14.20 Get Settings

HTTP

# 获取指定索引的settings
GET /twitter,kimchy/_settings
# 获取全部settings
GET /_all/_settings

Java

    /**
* 获取setting
* @return
* @throws IOException
*/
public static RestHighLevelClient getSetting() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
GetSettingsRequest request = new GetSettingsRequest().indices("china_index");
GetSettingsResponse getSettingsResponse = client.indices().getSettings(request, RequestOptions.DEFAULT);
ImmutableOpenMap<String, Settings> settings = getSettingsResponse.getIndexToSettings();
settings.forEach(e -> {
System.out.println(e.key);
Settings value = e.value;
value.keySet().forEach(k -> {
System.out.println(k + ":" + value.get(k));
});
});
return client;
}

结果:

china_index
index.creation_date:1545294776325
index.number_of_replicas:1
index.number_of_shards:1
index.provided_name:china_index
index.uuid:LYn6XQ_sRZCazMtweW31ZA
index.version.created:6050099

14.21 Put Template & Get Templates

# 索引模板
PUT _template/template_
{
"index_patterns": ["te*", "bar*"],
"settings": {
"number_of_shards": 1
},
"mappings": {
"my_doc": {
"_source": {
"enabled": false
},
"properties": {
"host_name": {
"type": "keyword"
},
"created_at": {
"type": "date",
"format": "EEE MMM dd HH:mm:ss Z YYYY"
}
}
}
}
}
# 删除模板
DELETE /_template/template_
# 获取模板
GET /_template/template_
# 获取所有模板
GET /_template
# 模板是否存在
HEAD _template/template_

14.22 Validate Query

    public static RestHighLevelClient validateQuery() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
// ValidateQueryRequest需要一个或多个索引来验证查询。如果没有提供索引,则在所有索引上执行请求。
ValidateQueryRequest request = new ValidateQueryRequest("twitter");
QueryBuilder builder = QueryBuilders
.boolQuery()
.must(QueryBuilders.queryStringQuery("*:*"))
.filter(QueryBuilders.termQuery("user", "kimchy"));
request.query(builder);
request.allShards(true);// 默认情况下,请求只在一个随机选择的分片上执行
request.explain(true);
request.rewrite(true);
ValidateQueryResponse response = client.indices().validateQuery(request, RequestOptions.DEFAULT);
boolean isValid = response.isValid();
int totalShards = response.getTotalShards();
int successfulShards = response.getSuccessfulShards();
int failedShards = response.getFailedShards();
System.out.println("isValid:" + isValid + ",totalShards:" + totalShards + ",successfulShards:" + successfulShards + ",failedShards:" + failedShards);
if (failedShards > 0) {
for(DefaultShardOperationFailedException failure: response.getShardFailures()) {
String failedIndex = failure.index();
int shardId = failure.shardId();
String reason = failure.reason();
System.out.println("failedIndex:" + failedIndex + ",shardId:" + shardId + ",reason:" + reason);
}
}
for(QueryExplanation explanation: response.getQueryExplanation()) {
String explanationIndex = explanation.getIndex();
int shardId = explanation.getShard();
String explanationString = explanation.getExplanation();
System.out.println("explanationIndex:" + explanationIndex + ",shardId:" + shardId + ",explanationString:" + explanationString);
}
return client;
}

结果:

isValid:true,totalShards:5,successfulShards:5,failedShards:0
explanationIndex:twitter,shardId:0,explanationString:ConstantScore(user:kimchy)
explanationIndex:twitter,shardId:1,explanationString:ConstantScore(user:kimchy)
explanationIndex:twitter,shardId:2,explanationString:ConstantScore(user:kimchy)
explanationIndex:twitter,shardId:3,explanationString:ConstantScore(user:kimchy)
explanationIndex:twitter,shardId:4,explanationString:ConstantScore(user:kimchy)

14.23 Get Index

HTTP

# 获取所有索引信息
GET /_all
# 单个索引信息
GET /twitter

Java

    /**
* 获取索引详细信息
* @return
* @throws IOException
*/
public static RestHighLevelClient getIndex() throws IOException {
RestHighLevelClient client = RestClientFactory.getInstance().getClient();
GetIndexRequest request = new GetIndexRequest().indices("_all"); // _all是关键字,列出所有索引信息。也可以是通配符*
GetIndexResponse indexResponse = client.indices().get(request, RequestOptions.DEFAULT); // Mappings
ImmutableOpenMap<String, ImmutableOpenMap<String, MappingMetaData>> mappings = indexResponse.getMappings();
mappings.forEach(e -> {
String key = e.key;
ImmutableOpenMap<String, MappingMetaData> map = e.value;
System.out.println("Index:" + key);
map.forEach(n -> {
String type = n.key;
MappingMetaData metaData = n.value;
System.out.println(type + "|" + metaData.getSourceAsMap());
});
}); // Aliases
System.out.println("**********************************");
ImmutableOpenMap<String, List<AliasMetaData>> aliases = indexResponse.getAliases();
aliases.forEach(e -> {
String key = e.key;
List<AliasMetaData> value = e.value;
System.out.println("----" + key + "----");
value.forEach(a -> {
System.out.println(a.alias());
});
});
// Settings
System.out.println("**********************************");
ImmutableOpenMap<String, Settings> defaultSettings = indexResponse.defaultSettings();
defaultSettings.forEach(e -> {
String key = e.key;
Settings value = e.value;
System.out.println("----" + key + "----");
value.keySet().forEach(k -> {
System.out.println(k + ":" + value.get(k));
});
});
ImmutableOpenMap<String, Settings> settings = indexResponse.getSettings();
settings.forEach(e -> {
String key = e.key;
Settings value = e.value;
System.out.println("----" + key + "----");
value.keySet().forEach(k -> {
System.out.println(k + ":" + value.get(k));
});
});
return client;
}

结果:

Index:china_shape_index
info|{properties={location={precision=100.0m, type=geo_shape}, remark={type=keyword}}}
Index:china_index
city|{properties={pName={type=keyword}, cName={type=text}, location={type=geo_point}}}
Index:books
java|{properties={title={type=text, fields={keyword={ignore_above=256, type=keyword}}}, user={type=text, fields={keyword={ignore_above=256, type=keyword}}}}}
Index:my_source_index2
Index:my_target_index2
Index:my_source_index
Index:users
info|{properties={address={analyzer=ik_max_word, type=text}, age={type=long}, username={type=keyword}}}
Index:my_target_index
Index:test
msg|{properties={message={analyzer=ik_max_word, type=text}}}
Index:.kibana_
doc|{dynamic=strict, properties={server={properties={uuid={type=keyword}}}, visualization={properties={savedSearchId={type=keyword}, description={type=text}, uiStateJSON={type=text}, title={type=text}, version={type=integer}, kibanaSavedObjectMeta={properties={searchSourceJSON={type=text}}}, visState={type=text}}}, graph-workspace={properties={numVertices={type=integer}, description={type=text}, numLinks={type=integer}, title={type=text}, version={type=integer}, kibanaSavedObjectMeta={properties={searchSourceJSON={type=text}}}, wsState={type=text}}}, kql-telemetry={properties={optInCount={type=long}, optOutCount={type=long}}}, type={type=keyword}, space={properties={color={type=keyword}, _reserved={type=boolean}, initials={type=keyword}, name={type=text, fields={keyword={ignore_above=2048, type=keyword}}}, description={type=text}}}, url={properties={accessCount={type=long}, accessDate={type=date}, url={type=text, fields={keyword={ignore_above=2048, type=keyword}}}, createDate={type=date}}}, migrationVersion={dynamic=true, type=object}, index-pattern={properties={notExpandable={type=boolean}, fieldFormatMap={type=text}, sourceFilters={type=text}, typeMeta={type=keyword}, timeFieldName={type=keyword}, intervalName={type=keyword}, fields={type=text}, title={type=text}, type={type=keyword}}}, search={properties={hits={type=integer}, columns={type=keyword}, description={type=text}, sort={type=keyword}, title={type=text}, version={type=integer}, kibanaSavedObjectMeta={properties={searchSourceJSON={type=text}}}}}, updated_at={type=date}, canvas-workpad={dynamic=false, properties={@created={type=date}, @timestamp={type=date}, name={type=text, fields={keyword={type=keyword}}}, id={index=false, type=text}}}, namespace={type=keyword}, telemetry={properties={enabled={type=boolean}}}, timelion-sheet={properties={hits={type=integer}, timelion_sheet={type=text}, timelion_interval={type=keyword}, timelion_columns={type=integer}, timelion_other_interval={type=keyword}, timelion_rows={type=integer}, description={type=text}, title={type=text}, version={type=integer}, kibanaSavedObjectMeta={properties={searchSourceJSON={type=text}}}, timelion_chart_height={type=integer}}}, config={dynamic=true, properties={buildNum={type=keyword}}}, dashboard={properties={hits={type=integer}, timeFrom={type=keyword}, timeTo={type=keyword}, refreshInterval={properties={display={type=keyword}, section={type=integer}, value={type=integer}, pause={type=boolean}}}, description={type=text}, uiStateJSON={type=text}, timeRestore={type=boolean}, title={type=text}, version={type=integer}, kibanaSavedObjectMeta={properties={searchSourceJSON={type=text}}}, optionsJSON={type=text}, panelsJSON={type=text}}}}}
Index:twitter
t_doc|{properties={msg={type=text, fields={keyword={ignore_above=256, type=keyword}}}, A={type=text, fields={keyword={ignore_above=256, type=keyword}}}, B={type=text, fields={keyword={ignore_above=256, type=keyword}}}, C={type=text, fields={keyword={ignore_above=256, type=keyword}}}, flag={type=text, fields={keyword={ignore_above=256, type=keyword}}}, D={type=text, fields={keyword={ignore_above=256, type=keyword}}}, color={type=text, fields={keyword={ignore_above=256, type=keyword}}}, updateUser={type=text, fields={keyword={ignore_above=256, type=keyword}}}, extMsg={type=text, fields={keyword={ignore_above=256, type=keyword}}}, counter={type=long}, message={type=text, fields={keyword={ignore_above=256, type=keyword}}}, field={type=text, fields={keyword={ignore_above=256, type=keyword}}}, size={type=text, fields={keyword={ignore_above=256, type=keyword}}}, post_date={type=date}, name={type=text, fields={keyword={ignore_above=256, type=keyword}}}, animal={properties={cat={type=text, fields={keyword={ignore_above=256, type=keyword}}}, dog={type=text, fields={keyword={ignore_above=256, type=keyword}}}}}, postDate={type=date}, hate={type=text, fields={keyword={ignore_above=256, type=keyword}}}, favorite={type=text, fields={keyword={ignore_above=256, type=keyword}}}, user={type=text, fields={keyword={ignore_above=256, type=keyword}}}}}
**********************************
----china_shape_index----
----.kibana_----
.kibana
----china_index----
----users----
----my_source_index----
----my_source_index2----
alias222
----my_target_index2----
my_search_indices
----my_target_index----
my_search_indices
----test----
----twitter----
----books----
**********************************
----my_target_index----
index.allocation.max_retries:
index.blocks.write:true
index.codec:best_compression
index.creation_date:
index.number_of_replicas:
index.number_of_shards:
index.provided_name:my_target_index
index.resize.source.name:my_source_index
index.resize.source.uuid:tSYNLldWQNCOlR5NJGaH9g
index.routing.allocation.initial_recovery._id:wCr6Uz0jTvGaTHh5acNxKA
index.routing_partition_size:
index.shrink.source.name:my_source_index
index.shrink.source.uuid:tSYNLldWQNCOlR5NJGaH9g
index.uuid:F976xviGQ965JU9patwQnA
index.version.created:
index.version.upgraded:
----twitter----
index.creation_date:
index.number_of_replicas:
index.number_of_shards:
index.provided_name:twitter
index.uuid:TLReCXTSSe6tvI7yNveWgw
index.version.created:
----books----
index.creation_date:
index.number_of_replicas:
index.number_of_shards:
index.provided_name:books
index.uuid:leQWEGe8So6B10awTItCNg
index.version.created:
----users----
index.creation_date:
index.number_of_replicas:
index.number_of_shards:
index.provided_name:users
index.uuid:tyxNGtSsThOFDaTBBy7jKQ
index.version.created:
----my_source_index----
index.blocks.write:true
index.creation_date:
index.number_of_replicas:
index.number_of_shards:
index.provided_name:my_source_index
index.uuid:tSYNLldWQNCOlR5NJGaH9g
index.version.created:
----my_source_index2----
index.blocks.write:true
index.creation_date:
index.number_of_replicas:
index.number_of_shards:
index.provided_name:my_source_index2
index.uuid:iuDENl3uQku0Ef6flu8S-Q
index.version.created:
----test----
index.creation_date:
index.number_of_replicas:
index.number_of_shards:
index.provided_name:test
index.uuid:qF3UiIqHTLK_X7FSUUhlGw
index.version.created:
----china_shape_index----
index.creation_date:
index.number_of_replicas:
index.number_of_shards:
index.provided_name:china_shape_index
index.uuid:jhwyVqR0RQywyf3n7W0maQ
index.version.created:
----china_index----
index.creation_date:
index.number_of_replicas:
index.number_of_shards:
index.provided_name:china_index
index.uuid:LYn6XQ_sRZCazMtweW31ZA
index.version.created:
----.kibana_----
index.auto_expand_replicas:-
index.creation_date:
index.number_of_replicas:
index.number_of_shards:
index.provided_name:.kibana_
index.uuid:IvzG6JhgRJ-GgwTDWmmirQ
index.version.created:
----my_target_index2----
index.blocks.write:true
index.creation_date:
index.number_of_replicas:
index.number_of_shards:
index.provided_name:my_target_index2
index.resize.source.name:my_source_index2
index.resize.source.uuid:iuDENl3uQku0Ef6flu8S-Q
index.routing_partition_size:
index.uuid:ZBnocs2bSker45kb2lXoRw
index.version.created:
index.version.upgraded: Process finished with exit code



ElasticSearch6.5.0 【Java客户端之REST Client】的更多相关文章

  1. asp.net权限认证:OWIN实现OAuth 2.0 之客户端模式(Client Credential)

    asp.net权限认证系列 asp.net权限认证:Forms认证 asp.net权限认证:HTTP基本认证(http basic) asp.net权限认证:Windows认证 asp.net权限认证 ...

  2. SpringBoot:elasticSearch 7.2.0 Java High Level REST Client 搜索 API

    Springboot整合最新版elasticSearch参考之前的文章:SpingBoot:整合ElasticSearch 7.2.0 Search API SearchRequest用于与搜索文档, ...

  3. 《ElasticSearch6.x实战教程》之复杂搜索、Java客户端(下)

    第八章-复杂搜索 黑夜给了我黑色的眼睛,我却用它寻找光明. 经过了解简单的API和简单搜索,已经基本上能应付大部分的使用场景.可是非关系型数据库数据的文档数据往往又多又杂,各种各样冗余的字段,组成了一 ...

  4. elasticsearch系列七:ES Java客户端-Elasticsearch Java client(ES Client 简介、Java REST Client、Java Client、Spring Data Elasticsearch)

    一.ES Client 简介 1. ES是一个服务,采用C/S结构 2. 回顾 ES的架构 3. ES支持的客户端连接方式 3.1 REST API ,端口 9200 这种连接方式对应于架构图中的RE ...

  5. ElasticSearch6.0 Java API 使用 排序,分组 ,创建索引,添加索引数据,打分等(一)

    ElasticSearch6.0  Java API  使用     排序,分组 ,创建索引,添加索引数据,打分等 如果此文章对你有帮助,请关注一下哦 1.1 搭建maven 工程  创建web工程 ...

  6. 《ElasticSearch6.x实战教程》之简单搜索、Java客户端(上)

    第五章-简单搜索 众里寻他千百度 搜索是ES的核心,本节讲解一些基本的简单的搜索. 掌握ES搜索查询的RESTful的API犹如掌握关系型数据库的SQL语句,尽管Java客户端API为我们不需要我们去 ...

  7. ElasticSearch6.5.0 【安装IK分词器】

    不得不夸奖一下ES的周边资源,比如这个IK分词器,紧跟ES的版本,卢本伟牛逼!另外ES更新太快了吧,几乎不到半个月一个小版本就发布了!!目前已经发了6.5.2,估计我还没怎么玩就到7.0了. 下载 分 ...

  8. Elasticsearch集群搭建及使用Java客户端对数据存储和查询

    本次博文发两块,前部分是怎样搭建一个Elastic集群,后半部分是基于Java对数据进行写入和聚合统计. 一.Elastic集群搭建 1. 环境准备. 该集群环境基于VMware虚拟机.CentOS ...

  9. Solr JAVA客户端SolrJ 4.9使用示例教程

    http://my.oschina.net/cloudcoder/blog/305024 简介 SolrJ是操作Solr的JAVA客户端,它提供了增加.修改.删除.查询Solr索引的JAVA接口.So ...

随机推荐

  1. selenium2 run in Jenkins GUI testing not visible or browser not open but run in background浏览器后台运行不可见

      http://wiki.hudson-ci.org/display/HUDSON/Tomcat Tomcat from Windows GUI Testing in Windows Most Wi ...

  2. centos7网络配置方法

    方法一:nmtui    这个是字符界面的图形化网络配置工具 方法二:nmcli 命令行配置 方法三:直接vim /etc/sysconfig/network-scripts/ens----  编辑 ...

  3. codeforces#410C Mike and gcd problem

    题目:Mike and gcd problem 题意:给一个序列a1到an ,如果gcd(a1,a2,...an)≠1,给一种操作,可以使ai和ai+1分别变为(ai+ai+1)和(ai-ai+1); ...

  4. RabbitMQ广播:fanout模式

    一. 消息的广播需要exchange:exchange是一个转发器,其实把消息发给RabbitMQ里的exchange fanout: 所有bind到此exchange的queue都可以接收消息,广播 ...

  5. 爬虫系列二(数据清洗--->bs4解析数据)

    一 BeautifulSoup解析 1 环境安装 - 需要将pip源设置为国内源,阿里源.豆瓣源.网易源等 - windows (1)打开文件资源管理器(文件夹地址栏中) (2)地址栏上面输入 %ap ...

  6. django 静态文件的配置

    静态文件简介 一.准备文件 Jquery3.3.1文件,文件目录创建 二.创建过程如图 STATIC_URL = '/static/' #静态文件的别名 STATICFILES_DIRS=[ os.p ...

  7. 平滑升级你的Nginx

    1.概述(可以直接跳过看第2部分) Nginx方便地帮助我们实现了平滑升级.其原理简单概括,就是: (1)在不停掉老进程的情况下,启动新进程. (2)老进程负责处理仍然没有处理完的请求,但不再接受处理 ...

  8. Storm入门(三)HelloWorld示例

    一.配置开发环境 storm有两种操作模式: 本地模式和远程模式.使用本地模式的时候,你可以在你的本地机器上开发测试你的topology, 一切都在你的本地机器上模拟出来; 用远程模式的时候你提交的t ...

  9. WPFの命中测试

    概述:  WPF中的Canvas是常用的一个绘图控件,可以方便地在Canvas中添加我们需要处理的各种元素如:图片.文字等.但Canvas中元素增加到一定数量,并且有重合的时候,我们如何通过在Canv ...

  10. Android--图片轮播(banner)

    使用步骤 Step 1.依赖banner Gradle dependencies{ compile 'com.youth.banner:banner:1.4.10' //最新版本 } 或者引用本地li ...