Java如何操作ElasticSearch,看这一篇就够了
Java操作ElasticSearch的几种方案
使用HTTP请求
直接使用 HTTP 请求,去操作 Es。HTTP 请求工具,可以使用 Java 自带的 HttpUrlConnection
。也可以使用一些 HTTP 请求库,例如 HttpClient
、OKHttp
、Spring 中的 RestTemplate
都可以,但是需要导入第三方库。
这种方式有一个弊端,就是要自己组装请求参数,自己去解析响应的 JSON。
示例:
- 查询
books索引
中的所有文档 - 使用JDK中自带的
HttpURLConnection
作为请求工具,直接请求ES服务端 pretty=true
美化返回的数据
public class JavaApiElasticSearch {
public static void main(String[] args) throws IOException {
//构建请求地址和参数
URL url = new URL("http://localhost:9200/books/_search?pretty=true");
HttpURLConnection response= (HttpURLConnection) url.openConnection();
//如果响应结果为状态码为200
if (response.getResponseCode() == 200) {
InputStream inputStream = response.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
String str=null;
while ((str = br.readLine()) != null) {
System.out.println(str);
}
br.close();
}
}
}
Low Level REST Client
用于 Es 的官方的低级客户端。这种方式允许通过 HTTP 与 Es 集群
进行通信,但是请求时候的 JSON 参数和响应的 JSON 参数交给用户去处理。这种方式好处就是兼容所有的 Es 版本。但是就是数据处理比较麻烦。
导入所需依赖:
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.10.0</version>
</dependency>
同步请求
public class JavaApiElasticSearch2 {
public static void main(String[] args) throws IOException {
//构建RestClient对象
RestClientBuilder builder = RestClient.builder(
new HttpHost("localhost", 9200, "http")
//如果还有其他es集群,直接添加即可
// new HttpHost("localhost", 9300, "http"),
// new HttpHost("localhost", 9400, "http")
);
//如果想在请求头添加参数
// builder.setDefaultHeaders(new Header[]{new BasicHeader("key", "value")});
RestClient restClient = builder.build();
//构建请求对象
Request request = new Request("GET", "/books/_search");
//添加请求参数
request.addParameter("pretty", "true");
//发送同步请求
Response response = restClient.performRequest(request);
//解析Response对象
BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String str=null;
while ((str = br.readLine()) != null) {
System.out.println(str);
}
br.close();
}
}
异步请求
public class JavaApiElasticSearch3 {
public static void main(String[] args) throws IOException {
//构建RestClient对象
RestClientBuilder builder = RestClient.builder(
new HttpHost("localhost", 9200, "http")
//如果还有其他es集群,直接添加即可
// new HttpHost("localhost", 9300, "http"),
// new HttpHost("localhost", 9400, "http")
);
//如果想在请求头添加参数
// builder.setDefaultHeaders(new Header[]{new BasicHeader("key", "value")});
RestClient restClient = builder.build();
//构建请求对象
Request request = new Request("GET", "/books/_search");
//添加请求参数
request.addParameter("pretty", "true");
//发送异步请求
restClient.performRequestAsync(request, new ResponseListener() {
@Override
public void onSuccess(Response response) {
try {
//解析Response对象
BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String str=null;
while ((str = br.readLine()) != null) {
System.out.println(str);
}
br.close();
restClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Exception e) {
}
});
}
}
携带JSON参数
public class JavaApiElasticSearch3 {
public static void main(String[] args) throws IOException {
//构建RestClient对象
RestClientBuilder builder = RestClient.builder(
new HttpHost("localhost", 9200, "http")
//如果还有其他es集群,直接添加即可
// new HttpHost("localhost", 9300, "http"),
// new HttpHost("localhost", 9400, "http")
);
//如果想在请求头添加参数
// builder.setDefaultHeaders(new Header[]{new BasicHeader("key", "value")});
RestClient restClient = builder.build();
//构建请求对象
Request request = new Request("GET", "/books/_search");
//添加请求参数
request.addParameter("pretty", "true");
//添加json参数
request.setEntity(new NStringEntity("{\"query\": {\"term\":{\"name\":\"java\"} }}", ContentType.APPLICATION_JSON));
//发送异步请求
restClient.performRequestAsync(request, new ResponseListener() {
@Override
public void onSuccess(Response response) {
try {
//解析Response对象
BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String str=null;
while ((str = br.readLine()) != null) {
System.out.println(str);
}
br.close();
restClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Exception e) {
}
});
}
}
High Level REST Client
从字面上来理解,这个叫做高级客户端,也是目前使用最多的一种客户端。它其实有点像之前的 TransportClient。
这个所谓的高级客户端它的内部其实还是基于低级客户端,只不过针对 ElasticSearch 它提供了更多的 API,将请求参数和响应参数都封装成了相应的 API,开发者只需要调用相关的方法就可以拼接参数或者解析响应结果。
Java High Level REST Client 中的每个 API 都可以同步或异步调用,同步方法返回一个响应对象,而异步方法的名称则以 Async 为后缀结尾,异步请求一般需要一个监听器参数,用来处理响应结果。
相对于低级客户端,高级客户端的兼容性就要差很多(因为 JSON 的拼接和解析它已经帮我们做好了)。高级客户端需要 JDK1.8 及以上版本并且依赖版本需要与 ElasticSearch 版本相同(主版本号需要一致,次版本号不必相同)。
举个简单例子:
7.0 客户端能够与任何 7.x ElasticSearch 节点进行通信,而 7.1 客户端肯定能够与 7.1,7.2 和任何后来的 7.x 版本进行通信,但与旧版本的 ElasticSearch 节点通信时可能会存在不兼容的问题。
以下所有章节内容都是基于
High Level REST Client
来操作的
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.10.0</version>
</dependency>
需要注意,依赖的版本和 Es 的版本要对应。
Java API Client (ES官方推荐)
从ElasticSearch 7.17
开始,ES作废Java REST Client
也就是High Level REST Client
和Java Transport Client
参考文档:https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/index.html
索引管理
创建/删除索引
- 删除索引
- 创建索引时配置
settings
信息:分片、副本等 - 创建索引时配置
mappings
信息:properites
属性。支持三种方式:- JSON字符串(常用)
- Map方式
- XContentBuilder对象
- 创建索引时为索引别名
- 将索引创建的时的
settings
、mappings
、alias
等配置全部通过JSON字符串创建。和kibana
中的json一致 - 请求超时时间,连接所有节点的超时时间
- 连接 master 节点的超时时间
- 索引的创建同样也支持
同步
和异步
public class JavaApiElasticSearch4 {
public static void main(String[] args) throws IOException {
RestHighLevelClient highLevelClient = new RestHighLevelClient(RestClient.builder(
//可以添加多个集群的客户端
new HttpHost("localhost", 9200, "http"))
);
//1、删除已经存在的索引 删除blog索引
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("blog");
highLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
//2、创建一个索引 创建blog索引
CreateIndexRequest createIndexRequest = new CreateIndexRequest("blog");
//3、配置 settings 信息,例如分片、副本等配置信息
createIndexRequest.settings(Settings.builder()
// 创建分片数为3
.put("index.number_of_shards", 3)
// 副本数为2
.put("index.number_of_replicas", 2)
);
//4、配置 mapping 信息,例如属性信息 有以下三种方式:
//4.1第一种:JSON 字符串
// createIndexRequest.mapping("{\n" +
// " \"properties\": {\n" +
// " \"title\":{\n" +
// " \"type\": \"keyword\"\n" +
// " }\n" +
// " }\n" +
// "}", XContentType.JSON);
//4.2第二种方式:通过 map 构建 mapping
// Map<String, String> titleProperties = new HashMap<>();
// titleProperties.put("type", "keyword");
// Map<String,Object> title=new HashMap<>();
// title.put("title", titleProperties);
// Map<String,Object> properties=new HashMap<>();
// properties.put("properties", title);
// createIndexRequest.mapping(properties);
//4.3第三种方式:通过 XContentBuilder
// XContentBuilder builder= XContentFactory.jsonBuilder();
// builder.startObject(); //{
// builder.startObject("properties"); //"properties":{
// builder.startObject("title"); // "title:{"
// builder.field("type", "keyword"); // "type" : "keyword"
// builder.endObject(); //"}"
// builder.endObject(); //"}"
// builder.endObject(); //"}"
// createIndexRequest.mapping(builder);
//5、给索引创建别名
// createIndexRequest.alias(new Alias("my_blog_alias"));
//6、将以上的配置 settings、mapping、alias 等配置全部使用json来配置
createIndexRequest.source("{\n" +
" \"mappings\": {\n" +
" \"properties\": {\n" +
" \"title\":{\n" +
" \"type\": \"keyword\"\n" +
" }\n" +
" }\n" +
" },\n" +
" \"settings\": {\n" +
" \"number_of_shards\": 3,\n" +
" \"number_of_replicas\": 3\n" +
" },\n" +
" \"aliases\": {\n" +
" \"my_blog\": {}\n" +
" }\n" +
"}",XContentType.JSON);
//7、执行创建索引操作 同步操作
// highLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
//8、请求超时时间,连接所有节点的超时时间
createIndexRequest.setTimeout(TimeValue.timeValueMinutes(2));
//9、连接 master 节点的超时时间
createIndexRequest.setMasterTimeout(TimeValue.timeValueMinutes(1));
//10、执行创建索引操作 异步操作
highLevelClient.indices().createAsync(createIndexRequest, RequestOptions.DEFAULT, new ActionListener<CreateIndexResponse>() {
@Override
public void onResponse(CreateIndexResponse createIndexResponse) {
//关闭client
try {
highLevelClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Exception e) {
}
});
//同步关闭
// highLevelClient.close();
}
}
查询索引是否存在
public class JavaApiElasticSearch5 {
public static void main(String[] args) throws IOException {
RestHighLevelClient highLevelClient = new RestHighLevelClient(RestClient.builder(
//可以添加多个集群的客户端
new HttpHost("localhost", 9200, "http"))
);
//判断索引是否存在
GetIndexRequest getIndexRequest = new GetIndexRequest("my_blog");
boolean exists = highLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
System.out.println("exists=" + exists);
//关闭客户端
highLevelClient.close();
}
}
关闭/打开索引
关闭索引,可以同时指定关闭多个索引。指定的索引不能为别名
public class JavaApiElasticSearch5 {
public static void main(String[] args) throws IOException {
RestHighLevelClient highLevelClient = new RestHighLevelClient(RestClient.builder(
//可以添加多个集群的客户端
new HttpHost("localhost", 9200, "http"))
);
//关闭索引
CloseIndexRequest closeIndexRequest = new CloseIndexRequest("blog");
CloseIndexResponse close = highLevelClient.indices().close(closeIndexRequest, RequestOptions.DEFAULT);
List<CloseIndexResponse.IndexResult> indices = close.getIndices();
for (CloseIndexResponse.IndexResult index : indices) {
System.out.println(index.getIndex());
}
//关闭客户端
highLevelClient.close();
}
}
打开索引
public class JavaApiElasticSearch5 {
public static void main(String[] args) throws IOException {
RestHighLevelClient highLevelClient = new RestHighLevelClient(RestClient.builder(
//可以添加多个集群的客户端
new HttpHost("localhost", 9200, "http"))
);
//打开索引
OpenIndexRequest openIndexRequest = new OpenIndexRequest("blog");
highLevelClient.indices().open(openIndexRequest, RequestOptions.DEFAULT);
//关闭客户端
highLevelClient.close();
}
}
索引修改
- 修改
settings
中的内容- "blocks.write": true 阻塞写
- "blocks.read": true 阻塞读
- "blocks.read_only": true 只读
public class JavaApiElasticSearch5 {
public static void main(String[] args) throws IOException {
RestHighLevelClient highLevelClient = new RestHighLevelClient(RestClient.builder(
//可以添加多个集群的客户端
new HttpHost("localhost", 9200, "http"))
);
//修改索引中的settings的内容
UpdateSettingsRequest request = new UpdateSettingsRequest("blog");
//设置要更改的属性 :开启阻塞写/阻塞读/只读等
request.settings(Settings.builder().put("index.blocks.write", true).build());
highLevelClient.indices().putSettings(request, RequestOptions.DEFAULT);
//关闭客户端
highLevelClient.close();
}
}
克隆索引
被克隆的索引需要是只读索引,可以通过索引修改中的方式设置索引为阻塞写
。不能修改为只读blocks.read_only
public class JavaApiElasticSearch5 {
public static void main(String[] args) throws IOException {
RestHighLevelClient highLevelClient = new RestHighLevelClient(RestClient.builder(
//可以添加多个集群的客户端
new HttpHost("localhost", 9200, "http"))
);
//克隆索引
ResizeRequest resizeRequest = new ResizeRequest("new_blog", "blog");
highLevelClient.indices().clone(resizeRequest, RequestOptions.DEFAULT);
//关闭客户端
highLevelClient.close();
}
}
查看索引
public class JavaApiElasticSearch5 {
public static void main(String[] args) throws IOException {
RestHighLevelClient highLevelClient = new RestHighLevelClient(RestClient.builder(
//可以添加多个集群的客户端
new HttpHost("localhost", 9200, "http"))
);
//查看索引 可以同时查看多个索引
GetSettingsRequest getSettingsRequest = new GetSettingsRequest().indices("blog");
//只获取索引的指定属性 若不设置,则返回索引的所有属性值
getSettingsRequest.names("index.number_of_shards");
GetSettingsResponse settings = highLevelClient.indices().getSettings(getSettingsRequest, RequestOptions.DEFAULT);
//获取索引的所有settings信息
ImmutableOpenMap<String, Settings> indexToSettings = settings.getIndexToSettings();
System.out.println(indexToSettings);
//获取索引的指定属性值 这里获取 blog 索引的 number_of_shards 值
System.out.println(settings.getSetting("blog", "index.number_of_shards"));
//关闭客户端
highLevelClient.close();
}
}
Refresh & Flush
Es 底层依赖 Lucene,而 Lucene 中有 reopen 和 commit 两种操作,还有一个特殊的概念叫做 segment。
Es 中,基本的存储单元是 shard,对应到 Lucene 上,就是一个索引,Lucene 中的索引由 segment 组成,每个 segment 相当于 es 中的倒排索引。每个 es 文档创建时,都会写入到一个新的 segment 中,删除文档时,只是从属于它的 segment 处标记为删除,并没有从磁盘中删除。
Lucene 中:
reopen 可以让数据搜索到,但是不保证数据被持久化到磁盘中。
commit 可以让数据持久化。
Es 中:
默认是每秒 refresh 一次(Es 中文档被索引之后,首先添加到内存缓冲区,refresh 操作将内存缓冲区中的数据拷贝到新创建的 segment 中,这里是在内存中操作的)。
flush 将内存中的数据持久化到磁盘中。一般来说,flush 的时间间隔比较久,默认 30 分钟。
public class JavaApiElasticSearch5 {
public static void main(String[] args) throws IOException {
RestHighLevelClient highLevelClient = new RestHighLevelClient(RestClient.builder(
//可以添加多个集群的客户端
new HttpHost("localhost", 9200, "http"))
);
RefreshRequest request = new RefreshRequest("blog");
highLevelClient.indices().refresh(request, RequestOptions.DEFAULT);
FlushRequest request1 = new FlushRequest("blog");
highLevelClient.indices().flush(request1, RequestOptions.DEFAULT);
//关闭客户端
highLevelClient.close();
}
}
索引别名
索引的别名类似于 MySQL 中的视图。
添加别名
- 给索引
books
添加别名my_books
public class JavaApiElasticSearch5 {
public static void main(String[] args) throws IOException {
RestHighLevelClient highLevelClient = new RestHighLevelClient(RestClient.builder(
//可以添加多个集群的客户端
new HttpHost("localhost", 9200, "http"))
);
IndicesAliasesRequest aliasesRequest=new IndicesAliasesRequest();
IndicesAliasesRequest.AliasActions aliasActions = new IndicesAliasesRequest.AliasActions(IndicesAliasesRequest.AliasActions.Type.ADD);
aliasActions.index("books").alias("my_books");
aliasesRequest.addAliasAction(aliasActions);
highLevelClient.indices().updateAliases(aliasesRequest, RequestOptions.DEFAULT);
//关闭客户端
highLevelClient.close();
}
}
- 添加一个带
filter
的别名 - 当通过
GET my_books_filter/_search
查询的时候会携带此filter
中的条件
public class JavaApiElasticSearch5 {
public static void main(String[] args) throws IOException {
RestHighLevelClient highLevelClient = new RestHighLevelClient(RestClient.builder(
//可以添加多个集群的客户端
new HttpHost("localhost", 9200, "http"))
);
IndicesAliasesRequest aliasesRequest=new IndicesAliasesRequest();
IndicesAliasesRequest.AliasActions aliasActions = new IndicesAliasesRequest.AliasActions(IndicesAliasesRequest.AliasActions.Type.ADD);
aliasActions.index("books").alias("my_books_filter").filter("{\n" +
" \"term\": {\n" +
" \"name\": {\n" +
" \"value\": \"java\"\n" +
" }\n" +
" }\n" +
"}");
aliasesRequest.addAliasAction(aliasActions);
highLevelClient.indices().updateAliases(aliasesRequest, RequestOptions.DEFAULT);
//关闭客户端
highLevelClient.close();
}
}
删除别名
public class JavaApiElasticSearch5 {
public static void main(String[] args) throws IOException {
RestHighLevelClient highLevelClient = new RestHighLevelClient(RestClient.builder(
//可以添加多个集群的客户端
new HttpHost("localhost", 9200, "http"))
);
IndicesAliasesRequest aliasesRequest=new IndicesAliasesRequest();
IndicesAliasesRequest.AliasActions aliasActions = new IndicesAliasesRequest.AliasActions(IndicesAliasesRequest.AliasActions.Type.REMOVE);
aliasActions.index("books").alias("my_books");
aliasesRequest.addAliasAction(aliasActions);
highLevelClient.indices().updateAliases(aliasesRequest, RequestOptions.DEFAULT);
//关闭客户端
highLevelClient.close();
}
}
第二种方式
public class JavaApiElasticSearch5 {
public static void main(String[] args) throws IOException {
RestHighLevelClient highLevelClient = new RestHighLevelClient(RestClient.builder(
//可以添加多个集群的客户端
new HttpHost("localhost", 9200, "http"))
);
DeleteAliasRequest deleteAliasRequest = new DeleteAliasRequest("books", "my_books_filter");
highLevelClient.indices().deleteAlias(deleteAliasRequest, RequestOptions.DEFAULT);
//关闭客户端
highLevelClient.close();
}
}
判断别名是否存在
public class JavaApiElasticSearch5 {
public static void main(String[] args) throws IOException {
RestHighLevelClient highLevelClient = new RestHighLevelClient(RestClient.builder(
//可以添加多个集群的客户端
new HttpHost("localhost", 9200, "http"))
);
//可以指定多个索引别名
GetAliasesRequest getAliasesRequest = new GetAliasesRequest("my_books");
//指定的索引,可以指定多个索引,如果不指定,则会搜索所有索引的别名
getAliasesRequest.indices("books");
boolean alias = highLevelClient.indices().existsAlias(getAliasesRequest, RequestOptions.DEFAULT);
System.out.println(alias);
//关闭客户端
highLevelClient.close();
}
}
获取别名
public class JavaApiElasticSearch5 {
public static void main(String[] args) throws IOException {
RestHighLevelClient highLevelClient = new RestHighLevelClient(RestClient.builder(
//可以添加多个集群的客户端
new HttpHost("localhost", 9200, "http"))
);
//可以指定多个索引别名
GetAliasesRequest getAliasesRequest = new GetAliasesRequest();
//指定的索引,可以指定多个索引,如果不指定,则会搜索所有索引的别名
getAliasesRequest.indices("books");
GetAliasesResponse getAliasesResponse = highLevelClient.indices().getAlias(getAliasesRequest, RequestOptions.DEFAULT);
Map<String, Set<AliasMetadata>> aliases = getAliasesResponse.getAliases();
System.out.println(aliases);
//关闭客户端
highLevelClient.close();
}
}
文档管理
添加文档
- 添加文档时需要指定索引,若指定的索引不存在,则会创建索引
- 添加文档时可以指定id:
- 如果不指定文档id,那么每次执行都会随机生成id,类型为添加
- 如果文档id不存在,则会添加
- 如果文档id存在,则会更新。这种会全部覆盖文档中的所有内容,如果想要更新某个字段,则这种方式不行
- 添加文档的方式有三种:JSON、Map、XContentBuilder
- 可以直接指定文档操作的类型:添加/更新
- 如果添加时文档id已经存在,那么直接抛出异常
- 创建文档时可以选择
同步
或者异步
- 创建文档之后:
- 获取创建的文档id
- 获取创建的文档的对应的索引名称
- 判断文档是否创建成功
- 判断文档是否更新成功
- 获取操作后的分片信息
- 判断分片是否存在异常(分片总数>分片操作成功数)
- 如果异常打印异常信息
public class JavaApiElasticSearch6 {
public static void main(String[] args) throws IOException {
RestHighLevelClient highLevelClient = new RestHighLevelClient(RestClient.builder(
//可以添加多个集群的客户端
new HttpHost("localhost", 9200, "http"))
);
//指定要创建文档的索引
//如果指定的索引不存在,默认会创建1个分片,1个副本的索引
IndexRequest indexRequest = new IndexRequest("book");
//指定文档id
//如果不指定文档id,那么每次执行都会随机生成id,类型为添加
//如果文档id不存在,则会添加
//如果文档id存在,则会更新
indexRequest.id("1");
//添加文档的方式有三种:JSON、Map、XContentBuilder
//这里采用JSON
indexRequest.source("{\n" +
" \"title\": \"西游记\",\n" +
" \"author\": \"吴承恩\"\n" +
"}", XContentType.JSON);
//直接指定操作的类型,添加/更新
//如果指定的id存在,那么直接报错
// indexRequest.opType(DocWriteRequest.OpType.CREATE);
//创建索引操作 同步
IndexResponse indexResponse = highLevelClient.index(indexRequest, RequestOptions.DEFAULT);
//创建索引操作 异步
// highLevelClient.indexAsync(indexRequest, RequestOptions.DEFAULT, new ActionListener<IndexResponse>() {}
//解析操作的结果
//获取操作后的文档id
String id = indexResponse.getId();
System.out.println("id = " + id);
//获取操作后的索引名称
String index = indexResponse.getIndex();
System.out.println("index = " + index);
//判断文档是否创建成功
if (indexResponse.getResult()== DocWriteResponse.Result.CREATED) {
System.out.println("文档添加成功");
}
//判断文档是否更新成功(如果id已经存在)
if (indexResponse.getResult()== DocWriteResponse.Result.UPDATED) {
System.out.println("文档更新成功");
}
//获取操作后的分片信息
ReplicationResponse.ShardInfo shardInfo = indexResponse.getShardInfo();
//判断是否有分片异常
//例如:只有一个ES实例,创建的索引为1个分片和1个副本,那么总分片数就是2,副本分片需要在另一个ES上。那么这是就会出现副本分片执行不到的情况
if (shardInfo.getTotal() != shardInfo.getSuccessful()) {
System.out.println("总分片不等于操作成功的分片,有分片异常");
}
//如果失败的分片数大于0
//如果分片执行异常才会进行为分片失败,分片执行不到不算异常,例如:副本数过多,ES节点数少的情况。
if (shardInfo.getFailed() > 0) {
//打印错误原因
for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) {
System.out.println("failure = " + failure.reason());
}
}
//关闭客户端
highLevelClient.close();
}
}
获取文档
- 根据 id 获取文档
- 执行操作后,可以判断文档是否存在,但是内容会返回_source数据内容,如果单纯想只判断文档是否存在,那么使用判断文档是否存在
public class JavaApiElasticSearch7 {
public static void main(String[] args) throws IOException {
RestHighLevelClient highLevelClient = new RestHighLevelClient(RestClient.builder(
//可以添加多个集群的客户端
new HttpHost("localhost", 9200, "http"))
);
//指定要查询的索引的文档id
GetRequest getRequest = new GetRequest("book","1");
//获取执行操作的结果
GetResponse getResponse = highLevelClient.get(getRequest, RequestOptions.DEFAULT);
//获取文档id
System.out.println("getResponse.getId() = " + getResponse.getId());
//获取索引名称
System.out.println("getResponse.getIndex() = " + getResponse.getIndex());
//判断文档是否存在
if (getResponse.isExists()) {
//如果文档存在
//获取版本号
System.out.println("getResponse.getVersion() = " + getResponse.getVersion());
//获取 _source 也就是数据内容
System.out.println("getResponse.getSourceAsString() = " + getResponse.getSourceAsString());
}else{
System.out.println("文档不存在");
}
//关闭客户端
highLevelClient.close();
}
}
判断文档是否存在
- 判断文档是否存在和获取文档的 API 是一致的。只不过在判断文档是否存在时,不需要获取 source。
public class JavaApiElasticSearch7 {
public static void main(String[] args) throws IOException {
RestHighLevelClient highLevelClient = new RestHighLevelClient(RestClient.builder(
//可以添加多个集群的客户端
new HttpHost("localhost", 9200, "http"))
);
//指定要查询的索引的文档id
GetRequest getRequest = new GetRequest("book","1");
//只需要判断是否存在即可,无需返回_source数据内容
getRequest.fetchSourceContext(new FetchSourceContext(false));
boolean exists = highLevelClient.exists(getRequest, RequestOptions.DEFAULT);
System.out.println(exists);
//关闭客户端
highLevelClient.close();
}
}
删除文档
- 通过id删除文档
- 删除文档的响应和添加文档成功的响应类似
public class JavaApiElasticSearch7 {
public static void main(String[] args) throws IOException {
RestHighLevelClient highLevelClient = new RestHighLevelClient(RestClient.builder(
//可以添加多个集群的客户端
new HttpHost("localhost", 9200, "http"))
);
//通过id删除指定索引中的指定文档
DeleteRequest deleteRequest = new DeleteRequest("book", "1");
DeleteResponse deleteResponse = highLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
System.out.println("response.getId() = " + deleteResponse.getId());
System.out.println("response.getIndex() = " + deleteResponse.getIndex());
System.out.println("response.getVersion() = " + deleteResponse.getVersion());
ReplicationResponse.ShardInfo shardInfo = deleteResponse.getShardInfo();
if (shardInfo.getTotal() != shardInfo.getSuccessful()) {
System.out.println("有分片存在问题");
}
if (shardInfo.getFailed() > 0) {
for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) {
System.out.println("failure.reason() = " + failure.reason());
}
}
//关闭客户端
highLevelClient.close();
}
}
更新文档
- 通过script脚本更新
- 通过JSON更新
- 通过Map更新
- 通过XContentBuilder更新
- 通过 upsert 更新
- 如果指定的文档id存在,那么就会执行UpdateRequest中的doc的方法 实现文档更新
- 如果指定的文档id不存在,那么会执行UpdateRequest的upsert的方法方法 实现文档新增
public class JavaApiElasticSearch7 {
public static void main(String[] args) throws IOException {
RestHighLevelClient highLevelClient = new RestHighLevelClient(RestClient.builder(
//可以添加多个集群的客户端
new HttpHost("localhost", 9200, "http"))
);
//通过id指定索引中的文档
UpdateRequest updateRequest = new UpdateRequest("book", "2");
//1、通过script脚本更新
// Map<String,Object> params= Collections.singletonMap("title","三国演义_3");
// //指定只需要更新的字段为_source中的name字段,并通过params参数传递进来
// Script script = new Script(ScriptType.INLINE, "painless", "ctx._source.title=params.title", params);
// updateRequest.script(script);
//2、通过JSON更新
// updateRequest.doc("{\"title\": \"三国演义\"}", XContentType.JSON);
//3、通过Map更新
// HashMap<String, Object> source = new HashMap<>();
// source.put("title", "三国_演义");
// updateRequest.doc(source);
//4、通过XContentBuilder更新
// XContentBuilder xContentBuilder= XContentFactory.jsonBuilder();
// xContentBuilder.startObject();
// xContentBuilder.field("title", "三国");
// xContentBuilder.endObject();
// updateRequest.doc(xContentBuilder);
//5、通过 upsert 更新
XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();
jsonBuilder.startObject();
jsonBuilder.field("title", "三国演义666");
jsonBuilder.endObject();
updateRequest.doc(jsonBuilder);
//如果指定的文档id存在,那么就会执行上述方法 实现文档更新
//如果指定的文档id不存在,那么会执行下述方法 实现文档新增
updateRequest.upsert("{\n" +
" \"title\": \"三国演义\"\n" +
"}", XContentType.JSON);
//处理响应结果
UpdateResponse updateResponse = highLevelClient.update(updateRequest, RequestOptions.DEFAULT);
System.out.println("response.getId() = " + updateResponse.getId());
System.out.println("response.getIndex() = " + updateResponse.getIndex());
System.out.println("response.getVersion() = " + updateResponse.getVersion());
if (updateResponse.getResult() == DocWriteResponse.Result.UPDATED) {
System.out.println("更新成功");
} else if (updateResponse.getResult() == DocWriteResponse.Result.CREATED) {
System.out.println("添加成功");
}
//关闭客户端
highLevelClient.close();
}
}