<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.4.3</version>
</dependency>

package com.cdkj.framework.es;

import com.cdkj.common.utils.StringUtils;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;
import java.util.Objects;

//@Slf4j
@Configuration
public class ElasticsearchRestClient {
private static final int ADDRESS_LENGTH = 2;
private static final String HTTP_SCHEME = "http";

/**
* 使用冒号隔开ip和端口1
*/
@Value("${elasticsearch.ip}")
String[] ipAddress;

@Bean
public RestClientBuilder restClientBuilder() {
HttpHost[] hosts = Arrays.stream(ipAddress)
.map(this::makeHttpHost)
.filter(Objects::nonNull)
.toArray(HttpHost[]::new);
//log.debug("hosts:{}", Arrays.toString(hosts));
return RestClient.builder(hosts);
}

//https://www.jianshu.com/p/0b4f5e41405e
@Bean(name = "highLevelClient")
public RestHighLevelClient highLevelClient(@Autowired RestClientBuilder restClientBuilder) {
// 设置超时时间,多次尝试同一请求时应该遵守的超时。默认值为30秒,与默认套接字超时相同。若自定义套接字超时,则应相应地调整最大重试超时
restClientBuilder.setMaxRetryTimeoutMillis(60000);
/** 配置异步请求的线程数量,Apache Http Async Client默认启动一个调度程序线程,以及由连接管理器使用的许多工作线程
(与本地检测到的处理器数量一样多,取决于Runtime.getRuntime().availableProcessors()返回的数量)。线程数可以修改如下,
这里是修改为1个线程,即默认情况
*/
restClientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpAsyncClientBuilder) {
return httpAsyncClientBuilder.setDefaultIOReactorConfig(
IOReactorConfig.custom().setIoThreadCount(2).build()
);
}
});
/**
配置请求超时,将连接超时(默认为1秒)和套接字超时(默认为30秒)增加,
这里配置完应该相应地调整最大重试超时(默认为30秒),即上面的setMaxRetryTimeoutMillis,一般于最大的那个值一致即60000
*/
restClientBuilder.setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
@Override
public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) {
// 连接5秒超时,套接字连接60s超时
return requestConfigBuilder.setConnectTimeout(5000).setSocketTimeout(60000);
}
});
/**
如果ES设置了密码,那这里也提供了一个基本的认证机制,下面设置了ES需要基本身份验证的默认凭据提供程序
*/
/* final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials("user", "password"));
restClientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
}
});*/

/**
上面采用异步机制实现抢先认证,这个功能也可以禁用,这意味着每个请求都将在没有授权标头的情况下发送,然后查看它是否被接受,
并且在收到HTTP 401响应后,它再使用基本认证头重新发送完全相同的请求,这个可能是基于安全、性能的考虑
*/
/* restClientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
// 禁用抢先认证的方式
httpClientBuilder.disableAuthCaching();
return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
}
});*/
/**
配置通信加密,有多种方式:setSSLContext、setSSLSessionStrategy和setConnectionManager(它们的重要性逐渐递增)
*/
/*KeyStore truststore = KeyStore.getInstance("jks");
try (InputStream is = Files.newInputStream(keyStorePath)) {
truststore.load(is, keyStorePass.toCharArray());
}
SSLContextBuilder sslBuilder = SSLContexts.custom().loadTrustMaterial(truststore, null);
final SSLContext sslContext = sslBuilder.build();
clientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
return httpClientBuilder.setSSLContext(sslContext);
}
});*/

return new RestHighLevelClient(restClientBuilder);
}


private HttpHost makeHttpHost(String s) {
assert StringUtils.isNotEmpty(s);
String[] address = s.split(":");
if (address.length == ADDRESS_LENGTH) {
String ip = address[0];
int port = Integer.parseInt(address[1]);
return new HttpHost(ip, port, HTTP_SCHEME);
} else {
return null;
}
}
}

package com.cdkj.project.elasticsearch;

import com.cdkj.common.utils.StringUtils;
import com.cdkj.framework.web.domain.AjaxResult;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.support.ActiveShardCount;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.action.support.replication.ReplicationResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.get.GetResult;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.elasticsearch.index.reindex.UpdateByQueryRequest;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

import static java.util.Collections.singletonMap;


/**
* 添加数据
*/
@RestController
@RequestMapping("/es/document")
public class IndexDocumentController {
@Autowired
RestHighLevelClient restHighLevelClient;
/**
* 索引数据
* @return
*/
@GetMapping("/indexDoc")
public AjaxResult indexDoc() throws IOException {
//准备json数据
Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("mobile", "13327236141");
jsonMap.put("longCode", "本课程主要从四个章节进行讲解: 1.微服务架构入门 2.spring cloud基础入门 3.实战Spring Boot 4.注册中心eureka。");
jsonMap.put("corpName", "YUFEI");
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy‐MM‐dd HH:mm:ss");
jsonMap.put("createDate",new Date());
jsonMap.put("sendDate", new Date());
jsonMap.put("corpName", "测试环境");
jsonMap.put("address", "测试环境1111111111111111111111");
jsonMap.put("smsContent", "测试环境哈哈哈哈哈,高级客户端将在内部创建低级客户端,用来执行基于提供的构建器的请求,并管理其生命周期。\n" +
"当不再需要时,需要关闭高级客户端实例,以便它所使用的所有资源以及底层的http客户端实例及其线程得到正确释放。可以通过close方法来完成,该方法将关闭内部的RestClient实例。");

//索引请求对象
IndexRequest indexRequest = new IndexRequest("request100", "testIndexTable");
//指定索引文档内容
indexRequest.source(jsonMap);
//索引响应对象
IndexResponse indexResponse = restHighLevelClient.index(indexRequest);
//获取响应结果
DocWriteResponse.Result result = indexResponse.getResult();
System.out.println(result);

return AjaxResult.success();
}
/**
* 批量创建document 更新索引
*/
@GetMapping("/bulkDoc")
public AjaxResult bulkAddEsDocument(){
BulkRequest bulkRequest = new BulkRequest();
for (int i = 0 ; i < 10 ; i ++){
Map<String, Object> jsonMap =new HashMap<>() ;
String id = String.valueOf(i);
/* if (StringUtils.isEmpty(id)) {
throw new IndexException(ResponseEnum.ID_NULL);
}*/
jsonMap.put("mobile", "13327236141"+i);
jsonMap.put("longCode", "本课程主要从四个章节进行讲解: 1.微服务架构入门 2.spring cloud基础入门 3.实战Spring Boot 4.注册中心eureka。");
jsonMap.put("corpName", "YUFEI"+i);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy‐MM‐dd HH:mm:ss");
jsonMap.put("createDate",new Date());
jsonMap.put("sendDate", new Date());
jsonMap.put("corpName", "测试环境");
jsonMap.put("smsContent", "测试环境哈哈哈哈哈,高级客户端将在内部创建低级客户端,用来执行基于提供的构建器的请求,并管理其生命周期。\n" +
"当不再需要时,需要关闭高级客户端实例,以便它所使用的所有资源以及底层的http客户端实例及其线程得到正确释放。可以通过close方法来完成,该方法将关闭内部的RestClient实例。"+i);
IndexRequest indexRequest = new IndexRequest("request", "testIndexTable").id(id);
indexRequest.source(jsonMap);
bulkRequest.add(indexRequest);
}
BulkResponse bulkResponse = null;
try {
bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
} catch (Exception e) {
// log.error("批量添加失败-->{}", e);
e.printStackTrace();
}

if (bulkResponse.hasFailures()) { //失败的数据
List<BulkItemResponse.Failure> failureList = new ArrayList<>();
for (BulkItemResponse bulkItemResponse : bulkResponse) {
if (bulkItemResponse.isFailed()) {
BulkItemResponse.Failure failure = bulkItemResponse.getFailure();
failureList.add(failure);
}
}
return AjaxResult.error("失败的数据",failureList);
}
return AjaxResult.success(bulkResponse.getIngestTook());
}
/**
* 删除document
*/
@GetMapping("/deleteDoc")
public AjaxResult deleteDoc(){
DeleteResponse deleteResponse = null;
try {
DeleteRequest deleteRequest = new DeleteRequest("request", "testIndexTable","2");
deleteResponse = restHighLevelClient.delete(deleteRequest,RequestOptions.DEFAULT);
}catch (Exception e){
//log.error("删除文档失败-->{}", e);
e.printStackTrace();
}
//删除结果
System.out.println(deleteResponse.getResult());
return AjaxResult.success(deleteResponse);
}
/**
* 更新索引
*/
@GetMapping("/updateDoc")
public AjaxResult updateDoc() throws Exception{
UpdateRequest request = new UpdateRequest(
"test",//索引
"_doc",//类型
"1");//文档ID

//更新API允许通过使用脚本或传递部分文档来更新现有文档。

//使用脚本
//方式1:该脚本可以作为内联脚本提供:
Map<String, Object> parameters = singletonMap("count", 4);//脚本参数
//使用painless语言和上面的参数创建一个内联脚本
Script inline = new Script(ScriptType.INLINE, "painless", "ctx._source.field += params.count", parameters);
request.script(inline);

//方式2:引用名称为increment-field的脚本,改脚本定义的位置还没搞清楚。
Script stored =
new Script(ScriptType.STORED, null, "increment-field", parameters);
request.script(stored);

//只更新部分
//更新部分文档时,更新的部分文档将与现有文档合并。

//方式1:使用字符串形式
UpdateRequest request1 = new UpdateRequest("posts", "doc", "1");
String jsonString = "{" +
"\"updated\":\"2017-01-01\"," +
"\"reason\":\"daily update\"" +
"}";
request1.doc(jsonString, XContentType.JSON);

//方式2:使用Map形式,会被自动转为json格式
Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("updated", new Date());
jsonMap.put("reason", "daily update");
UpdateRequest request2 = new UpdateRequest("posts", "doc", "1")
.doc(jsonMap);


//方式3:使用XContentBuilder形式
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
builder.field("updated", new Date());
builder.field("reason", "daily update");
}
builder.endObject();
UpdateRequest request3 = new UpdateRequest("posts", "doc", "1")
.doc(builder);


//方式4:使用Object key-pairs形式
UpdateRequest request4 = new UpdateRequest("posts", "doc", "1")
.doc("updated", new Date(),
"reason", "daily update");


//如果文档尚不存在,则可以使用upsert方法定义一些将作为新文档插入的内容:
//与部分文档更新类似,可以使用接受String,Map,XContentBuilder或Object key-pairs的方式来定义upsert文档的内容。
String jsonString1 = "{\"created\":\"2017-01-01\"}";
request.upsert(jsonString1, XContentType.JSON);

//=========================可选参数===========================
request.routing("routing");//设置routing值
request.parent("parent");//设置parent值

//设置超时:等待主分片变得可用的时间
request.timeout(TimeValue.timeValueSeconds(1));//TimeValue方式
request.timeout("1s");//字符串方式

//刷新策略
request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);//WriteRequest.RefreshPolicy实例方式
request.setRefreshPolicy("wait_for");//字符串方式

//如果要更新的文档在获取或者索引阶段已被另一操作更改,则重试更新操作的次数
request.retryOnConflict(3);

request.version(2);//设置版本

request.fetchSource(true); //启用_source检索,默认为禁用

//为特定字段配置_source_include
String[] includes = new String[]{"updated", "r*"};
String[] excludes = Strings.EMPTY_ARRAY;
request.fetchSource(new FetchSourceContext(true, includes, excludes));

//为指定字段配置_source_exclude
String[] includes1 = Strings.EMPTY_ARRAY;
String[] excludes1 = new String[]{"updated"};
request.fetchSource(new FetchSourceContext(true, includes1, excludes1));

request.detectNoop(false);//禁用noop检测

//无论文档是否存在,脚本都必须运行,即如果脚本尚不存在,则脚本负责创建文档。
request.scriptedUpsert(true);

//如果不存在,则表明部分文档必须用作upsert文档。
request.docAsUpsert(true);

//设置在继续更新操作之前必须激活的分片副本的数量。
request.waitForActiveShards(2);
//使用ActiveShardCount方式,可以是ActiveShardCount.ALL,ActiveShardCount.ONE或ActiveShardCount.DEFAULT(默认值)
request.waitForActiveShards(ActiveShardCount.ALL);

//同步执行
UpdateResponse updateResponse = restHighLevelClient.update(request);


//异步执行
//DeleteResponse 的典型监听器如下所示:
//异步方法不会阻塞并立即返回。
/* ActionListener<UpdateResponse > listener = new ActionListener<UpdateResponse >() {
@Override
public void onResponse(UpdateResponse updateResponse) {
//执行成功时调用。 Response以参数方式提供
}

@Override
public void onFailure(Exception e) {
//在失败的情况下调用。 引发的异常以参数方式提供
}
};
//异步执行获取索引请求需要将UpdateRequest 实例和ActionListener实例传递给异步方法:
client.updateAsync(request, listener);*/

//Update Response
//返回的UpdateResponse允许检索有关执行操作的信息,如下所示:
String index = updateResponse.getIndex();
String type = updateResponse.getType();
String id = updateResponse.getId();
long version = updateResponse.getVersion();
if (updateResponse.getResult() == DocWriteResponse.Result.CREATED) {
//处理第一次创建文档的情况(upsert)
} else if (updateResponse.getResult() == DocWriteResponse.Result.UPDATED) {
//处理文档被更新的情况
} else if (updateResponse.getResult() == DocWriteResponse.Result.DELETED) {
//处理文档已被删除的情况
} else if (updateResponse.getResult() == DocWriteResponse.Result.NOOP) {
//处理文档未受更新影响的情况,即文档上未执行任何操作(noop)
}

//当通过fetchSource方法在UpdateRequest中启用源检索时,响应会包含已更新文档:
GetResult result = updateResponse.getGetResult();//获取已更新的文档
if (result.isExists()) {
String sourceAsString = result.sourceAsString();//获取已更新的文档源(String方式)
Map<String, Object> sourceAsMap = result.sourceAsMap();//获取已更新的文档源(Map方式)
byte[] sourceAsBytes = result.source();//获取已更新的文档源(byte[]方式)
} else {
//处理不返回文档源的场景(默认就是这种情况)
}


//也可以检查分片失败:
ReplicationResponse.ShardInfo shardInfo = updateResponse.getShardInfo();
if (shardInfo.getTotal() != shardInfo.getSuccessful()) {
//处理成功分片数量少于总分片数量的情况
}
if (shardInfo.getFailed() > 0) {
for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) {
String reason = failure.reason();//处理潜在的失败
}
}

//当针对文档不存在时,响应404状态码,将引发ElasticsearchException,需要按如下方式处理:
UpdateRequest request5 = new UpdateRequest("posts", "type", "does_not_exist").doc("field", "value");
try {
UpdateResponse updateResponse5 = restHighLevelClient.update(request);
} catch (ElasticsearchException e) {
if (e.status() == RestStatus.NOT_FOUND) {
//处理由于文档不存在抛出的异常
}
}

//如果存在版本冲突,则会抛出ElasticsearchException:
UpdateRequest request6 = new UpdateRequest("posts", "doc", "1")
.doc("field", "value")
.version(1);
try {
UpdateResponse updateResponse6 = restHighLevelClient.update(request);
} catch(ElasticsearchException e) {
if (e.status() == RestStatus.CONFLICT) {
//引发的异常表示返回了版本冲突错误
}
}

return AjaxResult.success();
}
}

package com.cdkj.project.elasticsearch;

import com.cdkj.framework.es.ElasticsearchRestClient;
import com.cdkj.framework.web.domain.AjaxResult;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.snapshots.SnapshotShardsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;

/**
* https://www.cnblogs.com/ginb/p/8716485.html
* 测试创建索引
*/
@RestController
@RequestMapping("/es/index")
public class InsertIndexController {
@Autowired
RestHighLevelClient restHighLevelClient;
@GetMapping("/create")
public AjaxResult index() throws IOException {
/**
*
*/
// 创建索引 相当于数据区哭
CreateIndexRequest request = new CreateIndexRequest("request100");//创建索引
//创建的每个索引都可以有与之关联的特定设置。
request.settings(Settings.builder()
.put("index.number_of_shards", 3)
.put("index.number_of_replicas", 2)
);


//为索引设置一个别名
request.alias(
new Alias("twitter_alias2")
);
//XXXX 可以检查索引是否已经存在

//同步执行
CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(request);

//异步执行
//异步执行创建索引请求需要将CreateIndexRequest实例和ActionListener实例传递给异步方法:
//CreateIndexResponse的典型监听器如下所示:
//异步方法不会阻塞并立即返回。
/* ActionListener<CreateIndexResponse> listener = new ActionListener<CreateIndexResponse>() {
@Override
public void onResponse(CreateIndexResponse createIndexResponse) {
//如果执行成功,则调用onResponse方法;
System.out.println(createIndexResponse);
}
@Override
public void onFailure(Exception e) {
//如果失败,则调用onFailure方法。
System.out.println(e);
}
};
restHighLevelClient.indices().createAsync(request, listener);//要执行的CreateIndexRequest和执行完成时要使用的ActionListener
*/
//返回的CreateIndexResponse允许检索有关执行的操作的信息,如下所示:
boolean acknowledged = createIndexResponse.isAcknowledged();//指示是否所有节点都已确认请求
boolean shardsAcknowledged = createIndexResponse.isShardsAcknowledged();//指示是否在超时之前为索引中的每个分片启动了必需的分片副本数
buildIndexMapping(request,"testIndexTable");
return AjaxResult.success(shardsAcknowledged);
}



// type 相当于 表
private void buildIndexMapping(CreateIndexRequest request, String type) throws IOException {
XContentBuilder mappingBuilder = JsonXContent.contentBuilder() // schema
.startObject()
.startObject("properties")
.startObject("mobile")
.field("type", "keyword")
.field("index", "true")
.endObject()
.startObject("createDate")
.field("type", "date")
.field("index", "true")
.endObject()
.startObject("sendDate")
.field("type", "date")
.field("index", "true")
.endObject()
.startObject("longCode")
.field("type", "keyword")
.field("index", "true")
.endObject()
.startObject("corpName")
.field("type", "keyword")
.field("index", "true")
.endObject()
.startObject("smsContent")
.field("type", "text")
.field("index", "true") //分词器 https://www.jianshu.com/p/46d50922a6e7
.field("analyzer", "standard")
.endObject()
.startObject("state")
.field("type", "integer")
.field("index", "true")
.endObject()
.startObject("province")
.field("type", "keyword")
.field("index", "true")
.endObject()
.startObject("operatorId")
.field("type", "integer")
.field("index", "true")
.endObject()
.startObject("ipAddr")
.field("type", "ip")
.field("index", "true")
.endObject()

.startObject("replyTotal")
.field("type", "integer")
.field("index", "true")
.endObject()

.startObject("fee")
.field("type", "integer")
.field("index", "true")
.endObject()
.endObject()
.endObject();
request.mapping(type, mappingBuilder);
}
private void buildIndexMapping2(CreateIndexRequest request, String type) throws IOException {
XContentBuilder mappingBuilder = JsonXContent.contentBuilder() // schema
.startObject()
.startObject("properties")
.startObject("mobile")
.field("type", "keyword")
.field("index", "true")
.endObject()
.startObject("createDate")
.field("type", "date")
.field("index", "true")
.endObject()
.startObject("sendDate")
.field("type", "date")
.field("index", "true")
.endObject()
.startObject("longCode")
.field("type", "keyword")
.field("index", "true")
.endObject()
.startObject("corpName")
.field("type", "keyword")
.field("index", "true")
.endObject()
.startObject("smsContent")
.field("type", "text")
.field("index", "true") //分词器 https://www.jianshu.com/p/46d50922a6e7
.field("analyzer", "standard")
.endObject()
.startObject("state")
.field("type", "integer")
.field("index", "true")
.endObject()
.startObject("province")
.field("type", "keyword")
.field("index", "true")
.endObject()
.startObject("operatorId")
.field("type", "integer")
.field("index", "true")
.endObject()
.startObject("ipAddr")
.field("type", "ip")
.field("index", "true")
.endObject()

.startObject("replyTotal")
.field("type", "integer")
.field("index", "true")
.endObject()

.startObject("fee")
.field("type", "integer")
.field("index", "true")
.endObject()
.endObject()
.endObject();
request.mapping(type, mappingBuilder);
}
//删除索引库
public void deleteIndex() throws IOException {
//删除索引请求对象
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("xc_course5");
//删除索引
DeleteIndexResponse deleteIndexResponse = restHighLevelClient.indices().delete(deleteIndexRequest);
//删除索引响应结果
boolean acknowledged = deleteIndexResponse.isAcknowledged();
System.out.println(acknowledged);

}

}

package com.cdkj.project.elasticsearch;

import com.cdkj.framework.web.domain.AjaxResult;
import org.aspectj.weaver.AjAttribute;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
* 检索
*/
@RestController
@RequestMapping("/es/search")
public class SearchDocumentController {
@Autowired
RestHighLevelClient restHighLevelClient;
//根据id检索
@GetMapping("/id")
public AjaxResult serchDoc() throws Exception{
GetRequest getRequest = new GetRequest(
"request", "testIndexTable",
"8");
GetResponse getResponse = restHighLevelClient.get(getRequest);
boolean exists = getResponse.isExists();
Map<String, Object> sourceAsMap = getResponse.getSourceAsMap();
System.out.println(sourceAsMap);

return AjaxResult.success(sourceAsMap);
}
@GetMapping("/all")
public AjaxResult searchAll() throws Exception{
SearchRequest searchRequest = new SearchRequest("request");
searchRequest.types("testIndexTable");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
//source源字段过虑 (需要返回的字段,不需要返回的字段)
searchSourceBuilder.fetchSource(new String[]{}, new String[]{"mobile", "corpName"});
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
SearchHits hits = searchResponse.getHits();
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
String index = hit.getIndex();
String type = hit.getType();
String id = hit.getId();
float score = hit.getScore();
String sourceAsString = hit.getSourceAsString();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("name");
String studymodel = (String) sourceAsMap.get("studymodel");
String description = (String) sourceAsMap.get("description");
System.out.println(name);
System.out.println(studymodel);
System.out.println(description);
}
return AjaxResult.success(hits);
}

/**
* 分页查询
*/
@GetMapping("/pageSearch")
public AjaxResult pageSearch() throws Exception{
SearchRequest searchRequest = new SearchRequest("request");
searchRequest.types("testIndexTable");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
//分页查询,设置起始下标,从0开始
searchSourceBuilder.from(0);
//每页显示个数
searchSourceBuilder.size(1000);
//source源字段过虑
searchSourceBuilder.fetchSource(new String[]{"mobile", "id"}, new String[]{});
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
SearchHits hits = searchResponse.getHits();

return AjaxResult.success(hits);
}

/**
* 精确查询
* @return
*/
@GetMapping("/termSearch")
public AjaxResult termSearch() throws Exception {
SearchRequest searchRequest = new SearchRequest("request");
searchRequest.types("testIndexTable");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.termQuery("mobile", "133272361419"));
//source源字段过虑
searchSourceBuilder.fetchSource(new String[]{"mobile"}, new String[]{});
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
SearchHits hits = searchResponse.getHits();
return AjaxResult.success(hits);
}
/**
* 根据id精确查询
*/
@GetMapping("/findById")
public AjaxResult findById() throws Exception{
SearchRequest searchRequest = new SearchRequest("request");
searchRequest.types("testIndexTable");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
String[] split = new String[]{"9", "8"};
List<String> idList = Arrays.asList(split);
searchSourceBuilder.query(QueryBuilders.termsQuery("_id", idList));
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
SearchHits hits = searchResponse.getHits();
return AjaxResult.success(hits);
}
/**
* 根据关键字搜索
*/
@GetMapping("/testMatchQuery")
public AjaxResult testMatchQuery() throws Exception {
SearchRequest searchRequest = new SearchRequest("request");
searchRequest.types("testIndexTable");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//source源字段过虑
searchSourceBuilder.fetchSource(new String[]{}, new String[]{});
//匹配关键字(用keyword 切词的字段只能整个字段,类似精确检索,standard 切词的可以模糊检索)
searchSourceBuilder.query(
QueryBuilders.matchQuery("mobile", "1332723")
.operator(Operator.OR) //表示只要有一个词匹配上就得分,如果实现三个词至少有两个词匹配如何实现
.minimumShouldMatch("80%") // 占比至少80 设置匹配占比
);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
SearchHits hits = searchResponse.getHits();
SearchHit[] searchHits = hits.getHits();

return AjaxResult.success(searchHits);

}
}