一、
综述
1、常见的
Elasticsearch Java API
有四类
client
连接方式:
1.1、
TransportClient
(不推荐)
Elasticsearch原生的api,TransportClient可以支持2.x,5.x版本,TransportClient 将会在Elasticsearch 7.0弃用并在8.0中完成删除。
1.2、
RestClient
,
ES
官方推荐使用
1.3、
Jest
(不推荐)
是Java社区开发的,是Elasticsearch的Java Http Rest客户端。
1.4、
Spring Data Elasticsearch
与Spring生态对接,可以在web系统中整合到Spring中使用,与SpringBoot、SpringData版本容易冲突,而且往往很难跟上Elasticsearch版本的更新,比如SpringBoot目前的2.3.1.RELEASE,所支持Elasticsearch 7.6.2。
从使用上来说,Spring Data的使命是给各种数据访问提供统一的编程接口,不管是关系型数据库(如 MySQL),还是非关系数据库(如Redis),或者类似Elasticsearch这样的索引数据库。从而简化开发人员的代码,提高开发效率,也就是说,Spring Data想要把对任何数据的访问都抽象为类似接口,这就导致了 Spring Data Elasticsearch在基本查询上没问题,但是复杂查询(模糊、通配符、match查询、聚集查询等)就显得力不从心了,此时,我们还是只能使用原生查询。
2、REST Client介绍
Java REST Client有
Low Level和High Level
两种:
Java Low Level REST Client:
使用该客户端需要将HTTP请求的body手动拼成JSON格式,HTTP响应也必须将返回的JSON数据手动封装成对象,使用上更为原始。
Java High Level REST Client:
该客户端基于Low Level客户端实现,提供API解决Low Level客户端需要手动转换数据格式的问题。
ES的官网已经提供了非常详尽的API参考手册,参见:
https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/index.html
二、
REST Client使用
1、
Java Low Level REST Client
具体代码在模块es-low-level模块下
1.1、maven导入
<
dependencies
>
<
dependency
>
<
groupId
>org.elasticsearch.client</
groupId
>
<
artifactId
>elasticsearch-rest-client</
artifactId
>
<
version
>7.7.0</
version
>
</
dependency
>
</
dependencies
>
1.
2、配置访问
es
的请求
Map<String,String> params = Collections.EMPTY_MAP;
String jsonString =
“{”
+
”
\”
msg
\”
:
\”
Java Low Level REST Client
\”
”
+
“}”
;
System.out.println(jsonString);
HttpEntity entity =
new
NStringEntity(jsonString, ContentType.APPLICATION_JSON);
Request request =
new
Request(
“PUT”
,
“enjoy_test/_doc/6”
);
request.addParameters(params);
request.setEntity(entity);
1.
3、发送请求并接收应答
Response response = restClient.performRequest(request);
System.out.println(response);
System.out.println(EntityUtils.toByteArray(response.getEntity()));
因为Java Low Level REST Client用法比较原始,在实际工作中用的比较少所以大概了解下用法即可,对应的类是TestEsLowSdk。
2、
Java High Level REST Client
具体代码在模块es-high-level模块下
2.1、maven依赖导入
<
dependency
>
<
groupId
>org.elasticsearch.client</
groupId
>
<
artifactId
>elasticsearch-rest-high-level-client</
artifactId
>
<
version
>7.7.0</
version
>
</
dependency
>
代码对应的类是 TestEsHighSdk
2.2
、创建访问客户端
RestClientBuilder restClientBuilder = RestClient.builder(
new
HttpHost(
”
192
.
168
.
0
.1
01
”
,
9200
,
“http”
));
2
.3
、创建索引
/*创建索引*/
CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName);
/* 这里可以对索引对象进行属性设置 */
createIndexRequest.settings(Settings.builder()
.put(
“index.number_of_shards”
,
3
)
.put(
“index.codec”
,
“best_compression”
));
Map<String,Object> message =
new
HashMap<>();
message.put(
“type”
,
“text”
);
Map<String,Object> properties =
new
HashMap<>();
properties.put(
“message”
,message);
Map<String,Object> mapping =
new
HashMap<>();
mapping.put(
“properties”
,properties);
createIndexRequest.mapping(mapping);
createIndexRequest.mapping(
“{”
+
”
\”
msg
\”
:
\”
Java Low Level REST Client
\”
”
+
“}”
, XContentType.JSON);
XContentBuilder.builder()
//
CreateIndexResponse createIndexResponse
= restHighLevelClient.indices().create(createIndexRequest,RequestOptions.DEFAULT);
System.out.println(createIndexResponse.index());
System.out.println(createIndexResponse.isAcknowledged());
使用CreateIndexRequest进行索引创建,如果想要对索引进行静态配置,可以使用
request.settings
。配置索引的映射有好几种方式,比如我们想配置的索引映射是:
put /high_sdk/_mapping
{
“properties”: {
” message”: {
“type”: “text”
}
}
}
可以采用:
request.mapping(
“{\n” + ” \”properties\”: {\n” +” \”message\”: {\n” + ” \”type\”: \”text\”\n” + ” }\n” + ” }\n” + “}”,
XContentType.JSON);
也可以采用:
Map<String, Object> message = new HashMap<>();
message.put(“type”, “text”);
Map<String, Object> properties = new HashMap<>();
properties.put(“message”, message);
Map<String, Object> mapping = new HashMap<>();
mapping.put(“properties”, properties);
request.mapping(mapping);
还可以采用:
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{ builder.startObject(“properties”);
{ builder.startObject(“message”);
{ builder.field(“type”, “text”);}
builder.endObject();
}
builder.endObject();
}
builder.endObject();
request.mapping(builder);
然后通过client.indices().create方法将请求发送给es即可,es的应答将通过CreateIndexResponse返回给我们。
2.4
、索引
(
保存
)
文档
基本上和创建索引的思路是一样的
/*索引(保存)文档*/
IndexRequest indexRequest
=
new
IndexRequest(
indexName
);
indexRequest
.id(
docId
);
使用IndexRequest进行文档的索引,相关的请求体可以通过多种方法生成
XContentBuilder xContentBuilder
=
XContentFactory
.
jsonBuilder
();
xContentBuilder
.startObject();
{
xContentBuilder
.field(
“user”
,
”
hankin
”
);
xContentBuilder
.timeField(
“postData”
,
new
Date());
xContentBuilder
.field(
“message”
,
“Go ELK”
);
}
xContentBuilder
.endObject();
indexRequest
.source(
xContentBuilder
);
IndexResponse index
=
restHighLevelClient
.index(
indexRequest
,
RequestOptions
.
DEFAULT
);
System
.
out
.println(
index
.getIndex());
System
.
out
.println(
index
.getId());
然后通过client.index方法将请求发送给es即可,es的应答将通过CreateIndexResponse返回给我们。
2.5
、查询文档
使用GetRequest进行查询,通过client.get方法将请求发送给es即可,es的应答将通过GetResponse返回给我们。
/*查询文档*/
GetRequest getRequest
=
new
GetRequest(
indexName
,
docId
);
GetResponse getResponse
=
restHighLevelClient
.get(
getRequest
,
RequestOptions
.
DEFAULT
);
System
.
out
.println(
” get indexname = ”
+
getResponse
.getIndex());
if
(
getResponse
.isExists()){
System
.
out
.println(
“获取的文档:”
+
getResponse
.getSourceAsString());
}
else
{
System
.
out
.println(
“文档不存在”
);
}
更多的与检索相关的类或者方法,我们将在和SpringBoot的集成这个章节看到。
三、
SpringBoot
集成REST Client
1、环境配置
具体代码在模块springboot-highlevel模块下:
1.1、引入maven依赖:
<!– es–>
<
dependency
>
<
groupId
>org.elasticsearch</
groupId
>
<artifactId>elasticsearch</artifactId>
<version>7.7.0</version>
</
dependency
>
<
dependency
>
<
groupId
>org.elasticsearch.client</
groupId
>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.7.0</version>
</
dependency
>
为方便我们的使用,我们还会引入一些其他的组件,比如fastjson和Swagger2:
<!– fastjson–>
<
dependency
>
<
groupId
>com.alibaba</
groupId
>
<
artifactId
>fastjson</
artifactId
>
<
version
>1.2.
69
</
version
>
</
dependency
>
<!– Swagger2 –>
<
dependency
>
<
groupId
>io.springfox</
groupId
>
<
artifactId
>springfox-swagger2</
artifactId
>
<
version
>2.
9.2
</
version
>
</
dependency
>
<
dependency
>
<
groupId
>io.springfox</
groupId
>
<
artifactId
>springfox-swagger-ui</
artifactId
>
<
version
>2.
9.2
</
version
>
</
dependency
>
比较关键的类是:
- AggsSearch:聚集搜索服务类
- NormalSearch:一般搜索服务类
- OperateDoc:操作文档的服务
- OperateIndex:操作索引的服务
SendSearchRequest:通用的发送Search请求,并处理响应结果的服务。其中主要包括了索引的管理、文档的管理、_search接口基本用法、基于词项的查询、基于全文的查询、基于全文的模糊查询、组合查询、聚集查询的相关范例,详情参阅相关代码。
1.2、添加application.yml配置
server
:
port
:
8899
elasticsearch
:
host
: 192.168.0.101
port
: 9200
配置类代码实现:
@Configuration
public class
ESConfig
{
@Value
(
“${elasticsearch.host}”
)
private
String
host
;
@Value
(
“${elasticsearch.port}”
)
private int
port
;
@Bean
public
RestClientBuilder
restClientBuilder
() {
HttpHost httpHost
=
new
HttpHost(
host
,
port
,
“http”
);
RestClientBuilder restClientBuilder
=
RestClient
.
builder
(
httpHost
);
return
restClientBuilder
;
}
@Bean
public RestHighLevelClient highLevelClient(@Autowired RestClientBuilder restClientBuilder) {
return new RestHighLevelClient(restClientBuilder);
}
}
1.3、实体类代码
/**
* 给前端页面返回的应答实体
*/
public class ResponseBean {
//状态码
private
Integer
code
;
//返回信息
private
String
message
;
//返回的数据
private
Object
data
;
public
ResponseBean
(
Integer
code,
String
message,
Object
data) {
this
.
code
= code;
this
.
message
= message;
this
.
data
= data;
}
保存文档的实体:
public class
User
{
private
String
firstName
;
private
String
secondName
;
private
String
content
;
private
Integer
age
;
1.4、启动类代码实现:
@SpringBootApplication
public class
DemoApplication
{
public static void
main
(
String
[] args) {
SpringApplication
.
run
(
DemoApplication
.
class
, args);
}
}
2、测试代码实现
2.1、controller层代码实现
@Api
(value =
“ES测试接口”
, tags = {
“ES测试接口”
})
@RestController
@RequestMapping
(
“/es”
)
@CrossOrigin
(origins =
“*”
, methods = {
RequestMethod
.
GET
,
RequestMethod
.
POST
,
RequestMethod
.
DELETE
,
RequestMethod
.
PUT
})
public class
ESController
{
@Resource
private
OperateIndex
operateIndex
;
@Resource
private
OperateDoc
operateDoc
;
@Resource
private
NormalSearch
normalSearch
;
@Resource
private
AggsSearch
aggsSearch
;
private final
Logger
log
=
LoggerFactory
.
getLogger
(
ESConfig
.
class
);
private final static
String
KIBANA_SAMPLE_DATA_FLIGHTS
=
“kibana_sample_data_flights”
;
private final static
String
KIBANA_SAMPLE_DATA_LOGS
=
“kibana_sample_data_logs”
;
@ApiOperation
(value =
“es测试创建索引接口”
, notes =
“es测试创建索引接口”
)
@RequestMapping
(value =
“/index/creation”
, method =
RequestMethod
.
POST
)
public
ResponseBean
createIndex
(
@RequestParam
String
indexName) {
try
{
if
(
operateIndex
.createIndex(indexName)) {
return new
ResponseBean(
200
,
“创建成功”
,
null
);
}
else
{
return new
ResponseBean(
1002
,
“创建失败”
,
null
);
}
}
catch
(
IOException
e) {
e.printStackTrace();
}
return null
;
}
@ApiOperation
(value =
“es测试是否存在索引接口”
, notes =
“es测试是否存在索引接口”
)
@RequestMapping
(value =
“/index/existence”
, method =
RequestMethod
.
POST
)
public
ResponseBean
indexExists
(
@RequestParam
String
indexName) {
boolean
isExists
=
operateIndex
.isIndexExists(indexName);
String msg
=
isExists
?
“索引存在:”
+indexName :
“索引不存在:”
+indexName ;
return new
ResponseBean(
200
,
msg
,
isExists
);
}
@ApiOperation
(value =
“es测试删除索引接口”
, notes =
“es测试删除索引接口”
)
@RequestMapping
(value =
“/index/erasure”
, method =
RequestMethod
.
POST
)
public
ResponseBean
deleteIndex
(
@RequestParam
String
indexName) {
boolean
isDelete
=
operateIndex
.deleteIndex(indexName);
if
(
isDelete
) {
return new
ResponseBean(
200
,
“删除成功”
,
null
);
}
else
{
return new
ResponseBean(
10002
,
“删除失败”
,
null
);
}
}
@ApiOperation
(value =
“es测试插入文档接口”
, notes =
“es测试插入文档接口”
)
@RequestMapping
(value =
“/doc/insertion”
, method =
RequestMethod
.
POST
)
public
ResponseBean
insertDoc
(
@RequestBody
User
user,
@RequestParam
String
indexName,
@RequestParam
String
docId) {
return
operateDoc
.insertDoc(user,indexName,docId);
}
@ApiOperation
(value =
“es测试获取文档接口”
, notes =
“es测试插入文档接口”
)
@RequestMapping
(value =
“/doc/query”
, method =
RequestMethod
.
GET
)
public
ResponseBean
getDoc
(
@RequestParam
String
indexName,
@RequestParam
String
docId) {
return
operateDoc
.getDoc(indexName,docId);
}
@ApiOperation
(value =
“es测试更新文档接口”
, notes =
“es测试插入文档接口”
)
@RequestMapping
(value =
“/doc/update”
, method =
RequestMethod
.
POST
)
public
ResponseBean
updateDoc
(
@RequestParam
String
indexName,
@RequestParam
String
docId,
@RequestParam
String
fieldName,
@RequestParam
String
fieldValue) {
return
operateDoc
.updateDoc(indexName,docId,fieldName,fieldValue);
}
@ApiOperation
(value =
“es测试删除文档接口”
, notes =
“es测试插入文档接口”
)
@RequestMapping
(value =
“/doc/erasure”
, method =
RequestMethod
.
POST
)
public
ResponseBean
deleteDoc
(
@RequestParam
String
indexName,
@RequestParam
String
docId) {
return
operateDoc
.deleteDoc(indexName,docId);
}
@ApiOperation
(value =
“_search接口基本用法”
, notes =
“search接口基本用法”
)
@RequestMapping
(value =
“/search/example”
, method =
RequestMethod
.
POST
)
public
ResponseBean
searchExample
() {
return
normalSearch
.searchExample(
KIBANA_SAMPLE_DATA_FLIGHTS
);
}
@ApiOperation
(value =
“基于词项的查询”
, notes =
“基于词项的term查询”
)
@RequestMapping
(value =
“/search/term”
, method =
RequestMethod
.
POST
)
public
ResponseBean
termsBasedSearch
() {
return
normalSearch
.termsBasedSearch(
KIBANA_SAMPLE_DATA_FLIGHTS
,
“dayOfWeek”
);
}
@ApiOperation
(value =
“基于全文的查询”
, notes =
“基于全文的multi_match查询”
)
@RequestMapping
(value =
“/search/match”
, method =
RequestMethod
.
POST
)
public
ResponseBean
matchBasedSearch
() {
return
normalSearch
.matchBasedSearch(
KIBANA_SAMPLE_DATA_FLIGHTS
,
“AT”
,
“DestCountry”
,
“OriginCountry”
);
}
@ApiOperation
(value =
“基于全文的模糊查询”
, notes =
“基于全文的模糊查询”
)
@RequestMapping
(value =
“/search/fuzzy”
, method =
RequestMethod
.
POST
)
public
ResponseBean
fuzzySearch
() {
return
normalSearch
.fuzzySearch(
KIBANA_SAMPLE_DATA_LOGS
,
“message”
,
“firefix”
);
}
@ApiOperation
(value =
“组合查询范例”
, notes =
“组合查询之bool查询”
)
@RequestMapping
(value =
“/search/combination-bool”
, method =
RequestMethod
.
POST
)
public
ResponseBean
combinationSearch
() {
return
normalSearch
.boolSearch(
KIBANA_SAMPLE_DATA_LOGS
);
}
@ApiOperation
(value =
“聚集查询范例”
, notes =
“聚集查询范例”
)
@RequestMapping
(value =
“/search/aggsExample”
, method =
RequestMethod
.
POST
)
public
ResponseBean
aggsExampleSearch
() {
return
aggsSearch
.aggsExampleSearch(
KIBANA_SAMPLE_DATA_FLIGHTS
);
}
}
2.2、普通搜索业务代码实现:
@Service
public class
NormalSearch
{
@Resource
private
RestHighLevelClient
restHighLevelClient
;
@Resource
private
SendSearchRequest
sendSearchRequest
;
/**
* get kibana_sample_data_flights/_search
* {
* “from”:100,
* “size”:20,
* “query”:{
* “match_all”:{}
* },
* “_source”:[“Origin*”,”*Weather”],
* “sort”:[{“DistanceKilometers”:”asc”},{“FlightNum”:”desc”}]
* }
*/
public
ResponseBean
searchExample
(
String
indexName) {
SearchRequest searchRequest
=
new
SearchRequest();
searchRequest
.indices(indexName);
SearchSourceBuilder searchSourceBuilder
=
new
SearchSourceBuilder();
searchSourceBuilder
.from(
0
);
searchSourceBuilder
.size(
5
);
searchSourceBuilder
.query(
QueryBuilders
.
matchAllQuery
());
String
[]
includeFields
=
new
String[]{
“Origin*”
,
“*Weather”
};
searchSourceBuilder
.fetchSource(
includeFields
,
null
);
searchSourceBuilder
.sort(
new
FieldSortBuilder(
“DistanceKilometers”
).order(
SortOrder
.
ASC
));
searchSourceBuilder
.sort(
new
FieldSortBuilder(
“FlightNum”
).order(
SortOrder
.
DESC
));
searchRequest
.source(
searchSourceBuilder
);
return
sendSearchRequest
.send(
searchRequest
,
RequestOptions
.
DEFAULT
);
}
/**
* get kibana_sample_data_flights/_search
* {
* “query”:{
* “term”:{
* “dayOfWeek”:3
* }* }
* }
*/
public
ResponseBean
termsBasedSearch
(
String
indexName,
String
fieldName) {
SearchRequest searchRequest
=
new
SearchRequest();
searchRequest
.indices(indexName);
SearchSourceBuilder searchSourceBuilder
=
new
SearchSourceBuilder();
TermQueryBuilder termQueryBuilder
=
QueryBuilders
.
termQuery
(fieldName,
3
);
searchSourceBuilder
.query(
termQueryBuilder
);
searchRequest
.source(
searchSourceBuilder
);
return
sendSearchRequest
.send(
searchRequest
,
RequestOptions
.
DEFAULT
);
}
/**
* POST /kibana_sample_data_flights/_search
* {
* “query”: {
* “multi_match”: {
* “query”:”AT”,
* “fields”:[“DestCountry”, “OriginCountry”]
* }* }
* }
*/
public
ResponseBean
matchBasedSearch
(
String
indexName,
Object
text,
String
… fieldsName) {
SearchRequest searchRequest
=
new
SearchRequest();
searchRequest
.indices(indexName);
SearchSourceBuilder searchSourceBuilder
=
new
SearchSourceBuilder();
searchSourceBuilder
.query(
QueryBuilders
.
multiMatchQuery
(text,fieldsName));
searchRequest
.source(
searchSourceBuilder
);
return
sendSearchRequest
.send(
searchRequest
,
RequestOptions
.
DEFAULT
);
}
/**
* 基于全文的模糊查询
* get kibana_sample_data_logs/_search
* {
* “query”: {
* “fuzzy”: {
* “message”: {
* “value”: “firefix”,
* “fuzziness”: “1”
* }
* }
* }
* }
*/
public
ResponseBean
fuzzySearch
(
String
indexName,
String
fieldsName,
String
text) {
SearchRequest searchRequest
=
new
SearchRequest();
searchRequest
.indices(indexName);
SearchSourceBuilder searchSourceBuilder
=
new
SearchSourceBuilder();
// KIBANA_SAMPLE_DATA_LOGS, “message”,”firefix”
FuzzyQueryBuilder fuzzyQueryBuilder
=
QueryBuilders
.
fuzzyQuery
(fieldsName, text);
fuzzyQueryBuilder
.fuzziness(
Fuzziness
.
ONE
);
searchSourceBuilder
.query(
fuzzyQueryBuilder
);
searchRequest
.source(
searchSourceBuilder
);
return
sendSearchRequest
.send(
searchRequest
,
RequestOptions
.
DEFAULT
);
}
/**
* POST /kibana_sample_data_logs/_search
* {
* “query”: {
* “bool”: {
* “must”:[
* {“match”: { “message”: “firefox”} }
* ],
* “should”:[
* {“term”: { “geo. src”: “CN”}},
* {“term”: { “geo. dest”: “CN”}}
* ]
* }
* }
* }
*/
public
ResponseBean
boolSearch
(
String
indexName) {
SearchRequest searchRequest
=
new
SearchRequest();
searchRequest
.indices(indexName);
SearchSourceBuilder searchSourceBuilder
=
new
SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder
=
QueryBuilders
.
boolQuery
();
boolQueryBuilder
.must(
QueryBuilders
.
matchQuery
(
“message”
,
“firefox”
))
.should(
QueryBuilders
.
termQuery
(
“geo.src”
,
“CN”
))
.should(
QueryBuilders
.
termQuery
(
“geo.dest”
,
“CN”
));
searchSourceBuilder
.query(
boolQueryBuilder
);
searchRequest
.source(
searchSourceBuilder
);
return
sendSearchRequest
.send(
searchRequest
,
RequestOptions
.
DEFAULT
);
}
}
2.3、文档操作类代码实现
@Service
public class
OperateDoc
{
@Resource
private
RestHighLevelClient
restHighLevelClient
;
/**
* 创建文档
*/
public
ResponseBean
insertDoc
(
User
user,
String
indexName,
String
docId) {
IndexRequest indexRequest
=
new
IndexRequest(indexName);
String userJson
=
JSONObject
.
toJSONString
(user);
if
(!docId.equals(
“noid”
)){
indexRequest
.id(docId);
}
indexRequest
.source(
userJson
,
XContentType
.
JSON
);
try
{
IndexResponse indexResponse
=
restHighLevelClient
.index(
indexRequest
,
RequestOptions
.
DEFAULT
);
if
(
indexResponse
!=
null
){
String id
=
indexResponse
.getId();
String index
=
indexResponse
.getIndex();
if
(
indexResponse
.getResult() ==
DocWriteResponse
.
Result
.
CREATED
){
System
.
out
.println(
“新增文档成功”
);
return new
ResponseBean(
200
,
“索引文档成功”
,
id
);
}
else if
(
indexResponse
.getResult() ==
DocWriteResponse
.
Result
.
UPDATED
){
System
.
out
.println(
“覆盖文档成功”
);
return new
ResponseBean(
200
,
“覆盖文档成功”
,
null
);
}
}
}
catch
(
IOException
e) {
e.printStackTrace();
}
return null
;
}
/**
* 查询文档
*/
public
ResponseBean
getDoc
(
String
indexName,
String
docId) {
return new
ResponseBean(
200
,
“参考TestEsHighSdk”
,indexName+docId);
}
/**
* 更新文档
*/
public
ResponseBean
updateDoc
(
String
indexName,
String
docId,
String
fieldName,
String
fieldValue) {
try
{
XContentBuilder xContentBuilder
=
XContentFactory
.
jsonBuilder
();
xContentBuilder
.startObject();
{
xContentBuilder
.field(fieldName,fieldValue);
//xContentBuilder.timeField()
}
xContentBuilder
.endObject();
UpdateRequest request
=
new
UpdateRequest(indexName, docId).doc(
xContentBuilder
);
request
.docAsUpsert(
true
);
request
.fetchSource(
true
);
/*在应答里包含当前文档的内容*/
UpdateResponse updateResponse
=
restHighLevelClient
.update(
request
,
RequestOptions
.
DEFAULT
);
GetResult getResult
=
updateResponse
.getGetResult();
if
(
getResult
.isExists()){
String sourceAsString
=
getResult
.sourceAsString();
return new
ResponseBean(
200
,
“更新文档成功”
,
sourceAsString
);
}
else
{
return new
ResponseBean(
200
,
“更新文档失败”
,indexName+
“/”
+docId+
“/”
+fieldName);
}
}
catch
(
IOException
e) {
e.printStackTrace();
}
return null
;
}
/**
* 删除文档
*/
public
ResponseBean
deleteDoc
(
String
indexName,
String
docId) {
DeleteRequest deleteRequest
=
new
DeleteRequest(indexName, docId);
try
{
DeleteResponse deleteResponse
=
restHighLevelClient
.delete(
deleteRequest
,
RequestOptions
.
DEFAULT
);
if
(
deleteResponse
.getResult() ==
DocWriteResponse
.
Result
.
NOT_FOUND
){
return new
ResponseBean(
200
,
“删除不存在的文档”
,indexName+
“/”
+docId);
}
else
{
return new
ResponseBean(
200
,
“删除文档成功”
,indexName+
“/”
+docId);
}
}
catch
(
IOException
e) {
e.printStackTrace();
}
return null
;
}
}
2.4、索引管理代码实现
@Service
public class
OperateIndex
{
@Resource
private
RestHighLevelClient
restHighLevelClient
;
/**
* 新建索引
*/
public boolean
createIndex
(
String
indexName)
throws
IOException
{
XContentBuilder xContentBuilder
=
XContentFactory
.
jsonBuilder
()
.startObject().field(
“properties”
).startObject().field(
“firstName”
)
.startObject().field(
“type”
,
“keyword”
).endObject().field(
“secondName”
)
.startObject().field(
“type”
,
“keyword”
).endObject().field(
“age”
)
.startObject().field(
“type”
,
“integer”
).endObject().field(
“content”
)
.startObject().field(
“type”
,
“text”
).endObject()
.endObject().endObject();
CreateIndexRequest createIndexRequest
=
new
CreateIndexRequest(indexName);
createIndexRequest
.mapping(
xContentBuilder
);
CreateIndexResponse createIndexResponse
=
restHighLevelClient
.indices().create(
createIndexRequest
,
RequestOptions
.
DEFAULT
);
boolean
acknowledeg
=
createIndexResponse
.isAcknowledged();
return
acknowledeg
;
}
/**
* 查询是否存在
*/
public boolean
isIndexExists
(
String
indexName) {
GetIndexRequest getIndexRequest
=
new
GetIndexRequest(indexName);
getIndexRequest
.humanReadable(
true
);
boolean
exists =
false
;
try
{
exists =
restHighLevelClient
.indices().exists(
getIndexRequest
,
RequestOptions
.
DEFAULT
);
}
catch
(
IOException
e) {
e.printStackTrace();
}
return
exists;
}
/**
* 删除索引
*/
public boolean
deleteIndex
(
String
indexName) {
DeleteIndexRequest deleteIndexRequest
=
new
DeleteIndexRequest(indexName);
deleteIndexRequest
.indicesOptions(
IndicesOptions
.
LENIENT_EXPAND_OPEN
);
boolean
acknowledged =
false
;
try
{
AcknowledgedResponse delete
=
restHighLevelClient
.indices().delete(
deleteIndexRequest
,
RequestOptions
.
DEFAULT
);
acknowledged =
delete
.isAcknowledged();
}
catch
(
IOException
e) {
e.printStackTrace();
}
return
acknowledged;
}
}
2.5、聚集索引
@Service
public class
AggsSearch
{
@Resource
private
RestHighLevelClient
restHighLevelClient
;
@Resource
private
SendSearchRequest
sendSearchRequest
;
/**
* POST /kibana_sample_data_flights/_search?filter_path=aggregations
* {
* “query”: {
* “term”: {“OriginCountry”: “CN”}
* },
* “aggs”:
* {
* “date_price_histogram”: {
* “date_histogram”: {
* “field”: “timestamp”,
* “interval”: “month”
* },
* “aggs”: {
* “avg_price”: {“avg”: {“field”: “FlightDelayMin”}}
* }
* }
* }
* }
*/
public
ResponseBean
aggsExampleSearch
(
String
indexName) {
SearchRequest searchRequest
=
new
SearchRequest();
searchRequest
.indices(indexName);
/*query部分*/
SearchSourceBuilder searchSourceBuilder
=
new
SearchSourceBuilder();
searchSourceBuilder
.query(
QueryBuilders
.
termQuery
(
“OriginCountry”
,
“CN”
));
/*聚集部分*/
DateHistogramAggregationBuilder date_price_histogram
=
AggregationBuilders
.
dateHistogram
(
“date_price_histogram”
);
date_price_histogram
.field(
“timestamp”
).fixedInterval(
DateHistogramInterval
.
days
(
30
));
date_price_histogram
.subAggregation(
AggregationBuilders
.
avg
(
“avg_price”
).field(
“FlightDelayMin”
)
);
searchSourceBuilder
.aggregation(
date_price_histogram
);
searchRequest
.source(
searchSourceBuilder
);
JSONArray jsonArray
=
new
JSONArray();
try
{
SearchResponse searchResponse
=
sendSearchRequest
.sendAndProcessHits(
searchRequest
,
RequestOptions
.
DEFAULT
,
jsonArray
);
Aggregations aggregations
=
searchResponse
.getAggregations();
for
(
Aggregation aggregation
:
aggregations
){
String aggString
=
JSON
.
toJSONString
(
aggregation
);
jsonArray
.add(
JSON
.
parseObject
(
aggString
));
List
<?
extends
Histogram
.
Bucket
>
buckets
= ((
Histogram
)
aggregation
).getBuckets();
for
(
Histogram
.
Bucket bucket
:
buckets
){
System
.
out
.println(
“————————————–”
);
System
.
out
.println(
bucket
.getKeyAsString());
System
.
out
.println(
bucket
.getDocCount());
ParsedAvg parsedAvg
= (
ParsedAvg
)
bucket
.getAggregations().getAsMap().get(
“avg_price”
);
System
.
out
.println(
parsedAvg
.getValueAsString());
}
}
return new
ResponseBean(
200
,
“查询文档成功”
,
jsonArray
);
}
catch
(
IOException
e) {
e.printStackTrace();
return new
ResponseBean(
200
,
“查询文档失败”
,
null
);
}
}
}
2.6、发送请求代码实现
@Service
public class
SendSearchRequest
{
@Resource
private RestHighLevelClient restHighLevelClient;
/**
* 一般来说,非聚集的检索只需处理hits部分,直接将结果返回给前端
*/
public
ResponseBean
send
(
SearchRequest
searchRequest,
RequestOptions
options){
JSONArray jsonArray
=
new
JSONArray();
try
{
sendAndProcessHits(searchRequest,options,
jsonArray
);
return new
ResponseBean(
200
,
“查询文档”
,
jsonArray
);
}
catch
(
IOException
e) {
e.printStackTrace();
return new
ResponseBean(
200
,
“查询文档失败”
,
null
);
}
}
/**
* 处理返回结果中的hits部分
*/
public
SearchResponse
sendAndProcessHits
(
SearchRequest
searchRequest,
RequestOptions
options,
JSONArray
jsonArray)
throws
IOException
{
SearchResponse search
=
restHighLevelClient
.search(searchRequest, options);
SearchHits hits
=
search
.getHits();
for
(
SearchHit hit
:
hits
){
String src
=
hit
.getSourceAsString();
JSONObject jsonObject
=
JSON
.
parseObject
(
src
);
jsonArray.add(
jsonObject
);
}
return
search
;
}
}
代码参考地址:https://gitee.com/hankin_chj/es-platform.git