Elasticsearch快速使用教程
一、概述
ES是一个分布式的全文搜索引擎,为了解决原生Lucene使用的不足,优化Lucene的调用方式,并实现了高可用的分布式集群的搜索方案,ES的索引库管理支持依然是基于Apache Lucene™的开源搜索引擎。
ES也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的 RESTful API来隐Lucene的复杂性,从而让全文搜索变得简单。
二、下载安装
官网地址:Download Elasticsearch | Elastic
Kibana官网地址:Kibana 8.12.0 版本 |弹性的
内存配置:进入config>jvm.options 修改-Xms4g、-Xmx4g这两个默认的配置如下
-Xms512m
-Xmx512m
配置IP访问:进入config>elasticsearch.yml 加入一下配置
network.host: 0.0.0.0
http.port: 9200
cluster.initial_master_nodes: ["node-1", "node-2"]
跨域配置:进入config>elasticsearch.yml 加入一下配置,使head插件可以访问es
http.cors.enabled: true
http.cors.allow-origin: "*"
关闭账号认证:进入config>elasticsearch.yml 加入一下配置
xpack.security.enabled: false
启动:进入bin>elasticsearch.bat 以管理员方式运行
启动成功之后有两个重要端口分别是9200、9300
9200 | 9300 | |
---|---|---|
协议 | HTTP | TCP |
用途 | 默认HTTP通信端口,用于所有通过HTTP协议进行的API调用 | 用于集群中各节点之间的通信 |
交互对象 | 所有的客户端库都会使用该端口与Elasticsearch进行交互 | 仅用于集群内部节点之间的通信,不用于客户端与服务器之间的交互(从7.0版本开始,客户端不再直接与9300端口进行交互 |
细节 | 添加更新文档、检索数据、聚合查询等 | 节点操作、集群活动等 |
三、相关常用DSL语句
3.1 创建索引
// 创建索引包括索引的分片分区、映射,就相当于建数据库表
PUT /my_index
{
"settings": {
"index": {
"number_of_shards": 3, // 设置分片数量为3
"number_of_replicas": 1 // 设置副本数量为1
}
},
"mappings": {
"properties": {
"title": {
"type": "text", // 文本类型字段,用于全文搜索
"analyzer": "standard" // 使用标准分词器
},
"content": {
"type": "text",
"analyzer": "ik_smart" // 假设已安装IK分词器,使用ik_smart分词器进行中文分词
},
"author": {
"type": "keyword", // 关键字类型字段,不进行分词,用于精确匹配
"index": true // 允许对该字段进行索引
},
"publish_date": {
"type": "date", // 日期类型字段
"format": "yyyy-MM-dd" // 指定日期格式
},
"views": {
"type": "long", // 长整型字段,用于存储数值数据
"index": false // 不允许对该字段进行索引,节省存储空间和提高写入性能
}
}
}
}
- 索引名:索引名必须是唯一的,在同一个ES集群中不能存在同名的索引。
- 分片与副本:分片数量在索引创建后不能修改,副本数量可以在索引创建后动态调整。通常,分片数量应该根据集群的规模和预期的数据量进行合理规划。
- 字段类型:字段类型必须根据数据的实际类型进行指定,否则可能会导致数据写入错误或查询不准确。
- 映射冲突:如果在创建索引时指定的映射与已存在的映射冲突(例如,字段类型不匹配),ES会返回错误。因此,在创建索引前应该确保映射的一致性。
- 验证索引:创建索引后,可以使用GET请求验证索引是否存在。如果索引存在,ES会返回该索引的详细信息;如果索引不存在,ES会返回404错误。
常用字段类型 | 说明 |
---|---|
text | 用于全文搜索的文本数据。 数据会经过分词器处理,用于全文索引。 支持模糊、精确查询,但不支持聚合。 Elasticsearch默认会对text类型字段使用一个标准分析器,将其分词成多个单词,以便进行高效的全文搜索。 如果字段的类型是text,Elasticsearch会自动为其创建一个名为<字段名>.keyword的子字段,用于精确匹配查询。 |
keyword | 用于结构化数据的精确匹配。 适合存储不能分词的文本,如标签、用户名、状态等。 字段不会被分词器处理,而是作为完整的字符串存储。 支持模糊、精确查询,并支持聚合。 |
数值类型:byte、short、integer、long、float、double、half_float、scaled_float等 | 用于存储各种数字,包括整数和浮动小数。 数值字段会被建立索引,存储在有序的结构中,便于快速查找和范围查询。 |
date | 用于存储日期或时间戳。 日期字段会被转换为毫秒数(自Unix纪元以来的毫秒数),并存储在索引中。 这使得日期字段可以像数值字段一样进行排序和范围查询。 |
boolean | 用于存储布尔值(true或false)。 布尔字段被存储为true或false,并建立索引以便快速查找。 |
object | 用于存储嵌套的键值对,可以嵌套多层结构。 object类型字段会被扁平化并存储在主文档中。 |
nested | 也用于存储嵌套对象,但允许对嵌套对象内的字段进行查询和聚合。 nested类型字段作为独立的文档存储,并建立索引。 |
array | Elasticsearch中没有专门的数组数据类型。 但默认情况下,任意一个字段都可以包含0或多个值。 数组类型的各个元素值的数据类型必须相同。 |
3.2 查询索引
// 获取索引的完整元数据,包括设置和映射
GET /my_index
// 仅获取索引的设置信息
GET /my_index/_settings
// 仅获取索引的映射信息
GET /my_index/_mapping
// 查询所有索引库
GET _cat/indices?v
3.3 删除索引
// 删除索引库
DELETE aaa
3.4 更改索引
注意:不能更改索引的名称或分片的数量;由于直接修改映射的复杂性,通常建议在创建索引时就定义好映射,并尽量避免后续修改。如果需要更改现有字段的映射或添加复杂的新字段(如嵌套对象),通常最好的做法是:
- 创建一个新的索引,并定义正确的映射。
- 使用Elasticsearch的
reindex
API将数据从旧索引重新索引到新索引。 - (可选)删除旧索引
// 更改副本数量为1
PUT /my_index/_settings
{
"index" : {
"number_of_replicas" : 1
}
}
3.5 创建文档
POST /my_index/_doc
{
"title": "标题",
"content": "内容",
"author": "作者",
"publish_date": "2025-01-01"
"views": 99
}
3.6 查询文档
这是最简单的查询,它会返回索引中的所有文档。这对于测试或当你想要获取大量数据(但通常有限制,比如分页)时很有用
GET /my_index/_search
{
"query": {
"match_all": {}
}
}
3.6.1 精确值查询
精确值查询 使用term查询。这通常用于关键字(keyword)类型的字段
GET /my_index/_search
{
"query": {
"term": {
"author": "作者"
}
}
}
3.6.2 全文搜索查询
全文搜索查询 对于文本(text)类型的字段,match查询会执行全文搜索,它会对输入的文本进行分词,并搜索包含这些分词的文档
GET /my_index/_search
{
"query": {
"match": {
"title": "标题"
}
}
}
3.6.3 组合查询
组合查询 使用布尔查询来组合多个查询条件,比如must(必须满足)、should(应该满足,相当于OR)、must_not(必须不满足)和filter(过滤条件,不计算相关性得分)
GET /my_index/_search
{
"query": {
"bool": {
"must": [
{ "match": { "title": "标题" }},
{ "term": { "author": "作者" }}
],
"filter": [
{ "range": { "publish_date": { "gte": "2020-01-01" }}}
]
}
}
}
3.6.4 范围查询
范围查询 对于数值或日期字段,你可以使用范围查询来查找在某个范围内的文档
GET /my_index/_search
{
"query": {
"range": {
"publish_date": {
"gte": "2020-01-01",
"lte": "2025-12-31"
}
}
}
}
3.6.5 排序和分页
排序和分页 可以通过添加sort参数来对结果进行排序,并通过from和size参数来实现分页
GET /my_index/_search
{
"query": {
"match_all": {}
},
"sort": [
{ "publish_date": { "order": "desc" }}
],
"from": 0,
"size": 10
}
四、Java集成
pom文件按需引入
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>
<!-- Elasticsearch REST Client -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
</dependency>
<!-- Jackson Databind (用于处理JSON数据) -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
4.1 创建索引
public static void main(String[] args) throws IOException {
//创建ES客户端
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http"))
);
//创建索引 --- 请求对象
CreateIndexRequest request = new CreateIndexRequest("user");
//发送请求 --- 获取响应
CreateIndexResponse response = esClient.indices().create(request, RequestOptions.DEFAULT);
//响应状态
boolean acknowledged = response.isAcknowledged();
System.out.println("索引操作:" + acknowledged);
//关闭ES客户端
esClient.close();
}
4.2 查看索引
public static void main(String[] args) throws IOException {
//创建ES客户端
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http"))
);
//查询索引 --- 请求对象
GetIndexRequest request = new GetIndexRequest("user");
//发送请求 --- 获取响应
GetIndexResponse response = esClient.indices().get(request, RequestOptions.DEFAULT);
//响应状态
System.out.println(response.getAliases());
System.out.println(response.getMappings());
System.out.println(response.getSettings());
//关闭ES客户端
esClient.close();
}
4.3 删除索引
public static void main(String[] args) throws IOException {
//创建ES客户端
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http"))
);
//删除索引 --- 请求对象
DeleteIndexRequest request = new DeleteIndexRequest("user");
//发送请求 --- 获取响应
AcknowledgedResponse response = esClient.indices().delete(request,RequestOptions.DEFAULT);
//响应状态
System.out.println(response.isAcknowledged());
//关闭ES客户端
esClient.close();
}
4.4 创建文档
public static void main(String[] args) throws IOException {
//创建ES客户端
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http"))
);
//创建文档 --- 请求对象
IndexRequest request = new IndexRequest();
//设置索引及索引中文档的唯一性标识id(如果不指定,则ES会默认随机生成一个id)
request.index("user").id("1001");
//创建数据对象(文档内容)
User user = new User();
user.setName("张起灵");
user.setSex("man");
user.setAge(21);
//向ES中插入数据,必须将数据格式转换为JSON
ObjectMapper objectMapper = new ObjectMapper();
String userJson = objectMapper.writeValueAsString(user);
request.source(userJson, XContentType.JSON);
//发送请求 --- 获取响应
IndexResponse response = esClient.index(request, RequestOptions.DEFAULT);
System.out.println(response.getResult());
//关闭ES客户端
esClient.close();
}
4.5 修改文档
public static void main(String[] args) throws IOException {
//创建ES客户端
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http"))
);
//修改文档 --- 请求对象
UpdateRequest request = new UpdateRequest();
//配置修改参数 --- 表示要修改user索引中id为1001的文档内容
request.index("user").id("1001");
//将修改后的内容,以JSON格式写入请求体中
request.doc(XContentType.JSON,"age",18);
//发送请求 --- 获取响应
UpdateResponse response = esClient.update(request,RequestOptions.DEFAULT);
System.out.println(response.getResult());
//关闭ES客户端
esClient.close();
}
4.6 查询文档
public static void main(String[] args) throws IOException {
//创建ES客户端
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http"))
);
//查询文档 --- 请求对象
GetRequest request = new GetRequest();
//设置请求参数 --- 表示要查询user索引中id为1001的文档内容
request.index("user").id("1001");
//发送请求 --- 获取响应
GetResponse response = esClient.get(request,RequestOptions.DEFAULT);
System.out.println(response.getSourceAsString());
//关闭ES客户端
esClient.close();
}
4.7 删除文档
public static void main(String[] args) throws IOException {
//创建ES客户端
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http"))
);
//删除文档 --- 请求对象
DeleteRequest request = new DeleteRequest();
//设置请求参数 --- 表示要删除user索引中id为1001的文档
request.index("user").id("1001");
//发送请求 --- 获取响应
DeleteResponse response = esClient.delete(request,RequestOptions.DEFAULT);
System.out.println(response.getResult());
//关闭ES客户端
esClient.close();
}
4.8 批量创建文档
public static void main(String[] args) throws IOException {
//创建ES客户端
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http"))
);
//批量新增文档 --- 请求对象
BulkRequest request = new BulkRequest();
//以JSON格式批量新增文档 --- 存入请求体中
request.add(new IndexRequest().index("user").id("1001").source(XContentType.JSON, "name", "张起灵","sex","boy","age",21));
request.add(new IndexRequest().index("user").id("1002").source(XContentType.JSON, "name", "小哥","sex","boy","age",18));
request.add(new IndexRequest().index("user").id("1003").source(XContentType.JSON, "name", "小宋","sex","boy","age",20));
//发送请求 --- 获取响应
BulkResponse response = esClient.bulk(request, RequestOptions.DEFAULT);
System.out.println(response.getTook());
//关闭ES客户端
esClient.close();
}
4.9 批量删除文档
public static void main(String[] args) throws IOException {
//创建ES客户端
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http"))
);
//批量删除文档 --- 请求对象
BulkRequest request = new BulkRequest();
//将要删除的文档id存入请求体中
request.add(new DeleteRequest().index("user").id("1001"));
request.add(new DeleteRequest().index("user").id("1002"));
request.add(new DeleteRequest().index("user").id("1003"));
//发送请求 --- 获取响应
BulkResponse response = esClient.bulk(request,RequestOptions.DEFAULT);
System.out.println(response.getTook());
System.out.println(response.getItems());
//关闭ES客户端
esClient.close();
}
4.10 全量查询
public static void main(String[] args) throws IOException {
//创建ES客户端
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http"))
);
//1.查询索引中的全部文档 --- matchAllQuery 全量查询
//创建搜索请求对象
SearchRequest request = new SearchRequest();
//设置参数 --- 表示查询哪个索引中的文档内容
request.indices("user");
//构建查询的请求体 --- 存入搜索请求对象中
request.source(new SearchSourceBuilder().query(QueryBuilders.matchAllQuery()));
//发送请求 --- 获取响应
SearchResponse response = esClient.search(request,RequestOptions.DEFAULT);
//获取查询到的结果集
SearchHits hits = response.getHits();
System.out.println(hits.getTotalHits()); //结果集的条数
System.out.println(response.getTook()); //总耗时
//遍历结果集
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
//关闭ES客户端
esClient.close();
}
4.11 分页查询
public static void main(String[] args) throws IOException {
//创建ES客户端
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http"))
);
//3.分页查询
//创建搜索请求对象
SearchRequest request = new SearchRequest();
//设置参数 --- 表示查询哪个索引中的文档内容
request.indices("user");
//构建查询的请求体
SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
builder.from(0);
builder.size(2);
//将构建好的查询请求体存入搜索请求对象中
request.source(builder);
//发送请求 --- 获取响应
SearchResponse response = esClient.search(request,RequestOptions.DEFAULT);
//获取查询到的结果集
SearchHits hits = response.getHits();
System.out.println(hits.getTotalHits()); //结果集的条数
System.out.println(response.getTook()); //总耗时
//遍历结果集
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
//关闭ES客户端
esClient.close();
}
4.12 排序查询
public static void main(String[] args) throws IOException {
//创建ES客户端
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http"))
);
//4.对查询结果进行排序
//创建搜索请求对象
SearchRequest request = new SearchRequest();
//设置参数 --- 表示查询哪个索引中的文档内容
request.indices("user");
//构建查询的请求体
SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
builder.sort("age", SortOrder.DESC);
//将构建好的查询请求体存入搜索请求对象中
request.source(builder);
//发送请求 --- 获取响应
SearchResponse response = esClient.search(request,RequestOptions.DEFAULT);
//获取查询到的结果集
SearchHits hits = response.getHits();
System.out.println(hits.getTotalHits()); //结果集的条数
System.out.println(response.getTook()); //总耗时
//遍历结果集
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
//关闭ES客户端
esClient.close();
}
4.13 过滤字段查询
public static void main(String[] args) throws IOException {
//创建ES客户端
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http"))
);
//5.过滤字段
//创建搜索请求对象
SearchRequest request = new SearchRequest();
//设置参数 --- 表示查询哪个索引中的文档内容
request.indices("user");
//构建查询的请求体
SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
String[] excludes = {"sex"};
String[] includes = {};
builder.fetchSource(includes,excludes);
//将构建好的查询请求体存入搜索请求对象中
request.source(builder);
//发送请求 --- 获取响应
SearchResponse response = esClient.search(request,RequestOptions.DEFAULT);
//获取查询到的结果集
SearchHits hits = response.getHits();
System.out.println(hits.getTotalHits()); //结果集的条数
System.out.println(response.getTook()); //总耗时
//遍历结果集
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
//关闭ES客户端
esClient.close();
}
4.14 组合条件查询
public static void main(String[] args) throws IOException {
//创建ES客户端
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http"))
);
//6.组合查询
//创建搜索请求对象
SearchRequest request = new SearchRequest();
//设置参数 --- 表示查询哪个索引中的文档内容
request.indices("user");
//构建查询的请求体
SearchSourceBuilder builder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.should(QueryBuilders.matchQuery("age",18));
boolQueryBuilder.should(QueryBuilders.matchQuery("name","张起灵"));
builder.query(boolQueryBuilder);
//将构建好的查询请求体存入搜索请求对象中
request.source(builder);
//发送请求 --- 获取响应
SearchResponse response = esClient.search(request,RequestOptions.DEFAULT);
//获取查询到的结果集
SearchHits hits = response.getHits();
System.out.println(hits.getTotalHits()); //结果集的条数
System.out.println(response.getTook()); //总耗时
//遍历结果集
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
//关闭ES客户端
esClient.close();
}
4.15 范围查询
public static void main(String[] args) throws IOException {
//创建ES客户端
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http"))
);
//7.范围查询
//创建搜索请求对象
SearchRequest request = new SearchRequest();
//设置参数 --- 表示查询哪个索引中的文档内容
request.indices("user");
//构建查询的请求体
SearchSourceBuilder builder = new SearchSourceBuilder();
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age");
rangeQueryBuilder.gte(18);
rangeQueryBuilder.lt(25);
builder.query(rangeQueryBuilder);
//将构建好的查询请求体存入搜索请求对象中
request.source(builder);
//发送请求 --- 获取响应
SearchResponse response = esClient.search(request,RequestOptions.DEFAULT);
//获取查询到的结果集
SearchHits hits = response.getHits();
System.out.println(hits.getTotalHits()); //结果集的条数
System.out.println(response.getTook()); //总耗时
//遍历结果集
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
//关闭ES客户端
esClient.close();
}
4.16 模糊查询
public static void main(String[] args) throws IOException {
//创建ES客户端
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http"))
);
//8.模糊查询
//创建搜索请求对象
SearchRequest request = new SearchRequest();
//设置参数 --- 表示查询哪个索引中的文档内容
request.indices("user");
//构建查询的请求体
SearchSourceBuilder builder = new SearchSourceBuilder();
//FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("name","小张");
//fuzzyQueryBuilder.fuzziness(Fuzziness.ONE);
//builder.query(fuzzyQueryBuilder);
//上面三行代码 等价于 下面这行代码
builder.query(QueryBuilders.fuzzyQuery("name","小张").fuzziness(Fuzziness.ONE));
//将构建好的查询请求体存入搜索请求对象中
request.source(builder);
//发送请求 --- 获取响应
SearchResponse response = esClient.search(request,RequestOptions.DEFAULT);
//获取查询到的结果集
SearchHits hits = response.getHits();
System.out.println(hits.getTotalHits()); //结果集的条数
System.out.println(response.getTook()); //总耗时
//遍历结果集
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
//关闭ES客户端
esClient.close();
}
4.17 聚合查询
public static void main(String[] args) throws IOException {
//创建ES客户端
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http"))
);
//9.聚合查询
//创建搜索请求对象
SearchRequest request = new SearchRequest();
//设置参数 --- 表示查询哪个索引中的文档内容
request.indices("user");
//构建查询的请求体
SearchSourceBuilder builder = new SearchSourceBuilder();
AggregationBuilder aggregationBuilder = AggregationBuilders.max("maxAge").field("age");
builder.aggregation(aggregationBuilder);
//将构建好的查询请求体存入搜索请求对象中
request.source(builder);
//发送请求 --- 获取响应
SearchResponse response = esClient.search(request,RequestOptions.DEFAULT);
//获取查询到的结果集
SearchHits hits = response.getHits();
System.out.println(hits.getTotalHits()); //结果集的条数
System.out.println(response.getTook()); //总耗时
//遍历结果集
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
//关闭ES客户端
esClient.close();
}
4.18 分组查询
public static void main(String[] args) throws IOException {
//创建ES客户端
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http"))
);
//10.分组查询
//创建搜索请求对象
SearchRequest request = new SearchRequest();
//设置参数 --- 表示查询哪个索引中的文档内容
request.indices("user");
//构建查询的请求体
SearchSourceBuilder builder = new SearchSourceBuilder();
AggregationBuilder aggregationBuilder = AggregationBuilders.terms("ageGroup").field("age");
builder.aggregation(aggregationBuilder);
//将构建好的查询请求体存入搜索请求对象中
request.source(builder);
//发送请求 --- 获取响应
SearchResponse response = esClient.search(request,RequestOptions.DEFAULT);
//获取查询到的结果集
SearchHits hits = response.getHits();
System.out.println(hits.getTotalHits()); //结果集的条数
System.out.println(response.getTook()); //总耗时
//遍历结果集
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
//关闭ES客户端
esClient.close();
}