我们日常开发中,操作数据库写sql倒是不可能忘记,但是操作es的dsl语句有时候很容易忘记,特地记录一下方便查找。
-- 创建索引
PUT /my_index
{
"mappings": {
"properties": {
"title": {
"type": "text"
},
"description": {
"type": "text"
},
"timestamp": {
"type": "date"
}
}
}
}
-- 插入文档
POST /my_index/_doc/主键值
{
"title": "Sample Document",
"description": "This is a sample document for Elasticsearch",
"timestamp": "2022-01-01"
}
-- 更新文档
POST /my_index/_update/主键值
{
"doc": {
"description": "Updated description"
}
}
-- 删除单条文档
DELETE /my_index/_doc/主键值
或者
-- 删除单条文档
POST 索引名/_delete_by_query
{
"query":{
"term":{
"_id":4043
}
}
}
-- 删除索引中的所有数据
POST my_index/_delete_by_query
{
"query": {
"match_all": {
}
}
}
-- 删除索引
DELETE /my_index
-- 设置索引别名
POST /_aliases
{
"actions": [
{"add": {"index": "my_index2", "alias": "my_index"}}
]
}
-- 设置切片和副本数量
PUT your_index
{
"mappings" : {
"properties" : {
#索引字段(略)
}
}
"settings" : {
"number_of_shards" : 3,
"number_of_replicas" : 1
}
}
-- 查询单个字段内容
POST /my_index/_search
{
"query": {
"bool": {
"must": {
"term": {
"messageId": "CS202303160008-2"
}
}
}
}
}
-- 查询单个字段的多个内容 类似mysql中的in 用terms 多了个s
POST /my_index/_search
{
"query": {
"bool": {
"must": {
"terms": {
"messageId": ["22222","1111"]
}
}
}
}
}
-- 分页排序查询 不带其他条件
POST /my_index/_search
{
"query": {
"match_all": {}
},
"from": 0,
"size": 20,
"sort": [
{
"createdAt": {
"order": "desc"
}
}
]
}
-- 分页排序查询 带其他条件
{
"query": {
"bool": {
"must": [
{
"prefix": {
"action": "aa开头"
}
},
{
"wildcard": {
"param": "*左右匹配内容*"
}
}
],
"must_not": [],
"should": []
}
},
"from": 0,
"size": 10,
"sort": [
{
"createdAt": {
"order": "desc"
}
}
]
}
POST /my_index/_count
{
"query": {
"bool": {
"must": {
"term": {
"messageId": "CS202303160008-2"
}
}
}
}
}
4.0.0
com.demo.sdk
elasticsearch-util
1.0.0-SNAPSHOT
jar
elasticsearch-util
Spring Boot Support for elasticsearch-util
11
7.10.0
2.7.0
5.8.15
1.4.2
org.springframework.boot
spring-boot-autoconfigure
${spring-boot.version}
org.springframework.boot
spring-boot-configuration-processor
${spring-boot.version}
true
org.springframework.boot
spring-boot-starter-logging
${spring-boot.version}
org.elasticsearch.client
elasticsearch-rest-high-level-client
${elasticsearch.version}
com.github.pagehelper
pagehelper-spring-boot-starter
${pagehelper.version}
cn.hutool
hutool-all
${hutool.version}
org.apache.maven.plugins
maven-compiler-plugin
3.8.1
11
UTF-8
org.apache.maven.plugins
maven-source-plugin
true
compile
jar
import cn.hutool.core.text.CharSequenceUtil;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* ES配置类
* @author ppp
* @date 2023/3/21
*/
@ConfigurationProperties(prefix = "elasticsearch.config")
public class ElasticsearchProperties {
/**
* 域名
*/
private String host;
/**
* 端口
*/
private String port;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 连接超时时间
*/
private int connectTimeOut;
/**
* 连接超时时间
*/
private int socketTimeOut;
/**
* 获取连接的超时时间
*/
private int connectionRequestTimeOut;
/**
* 获取搜索的超时时间
*/
private long searchRequestTimeOut = 10000L;
/**
* 最大连接数
*/
private int maxConnectNum;
/**
* 最大路由连接数
*/
private int maxConnectPerRoute;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
public int getConnectTimeOut() {
return connectTimeOut;
}
public void setConnectTimeOut(int connectTimeOut) {
this.connectTimeOut = connectTimeOut;
}
public int getSocketTimeOut() {
return socketTimeOut;
}
public void setSocketTimeOut(int socketTimeOut) {
this.socketTimeOut = socketTimeOut;
}
public int getConnectionRequestTimeOut() {
return connectionRequestTimeOut;
}
public void setConnectionRequestTimeOut(int connectionRequestTimeOut) {
this.connectionRequestTimeOut = connectionRequestTimeOut;
}
public long getSearchRequestTimeOut() {
return searchRequestTimeOut;
}
public void setSearchRequestTimeOut(long searchRequestTimeOut) {
this.searchRequestTimeOut = searchRequestTimeOut;
}
public int getMaxConnectNum() {
return maxConnectNum;
}
public void setMaxConnectNum(int maxConnectNum) {
this.maxConnectNum = maxConnectNum;
}
public int getMaxConnectPerRoute() {
return maxConnectPerRoute;
}
public void setMaxConnectPerRoute(int maxConnectPerRoute) {
this.maxConnectPerRoute = maxConnectPerRoute;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public CredentialsProvider getCredentialsProvider() {
if (CharSequenceUtil.isNotBlank(username) && CharSequenceUtil.isNotBlank(password)) {
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
return credentialsProvider;
}
return null;
}
}
import cn.hutool.core.text.CharSequenceUtil;
import com.demo.sdk.elasticsearch.template.ElasticsearchUtilTemplate;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* ES工具自动配置类
* @author ppp
* @date 2023/3/21
*/
@Configuration
@ConditionalOnClass(ElasticsearchUtilTemplate.class)
@EnableConfigurationProperties(ElasticsearchProperties.class)
public class ElasticsearchUtilAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RestHighLevelClient esRestClient(ElasticsearchProperties esearchProperties) {
if (esearchProperties == null) {
throw new NullPointerException("Es Configuration Properties Is Null");
}
String host = esearchProperties.getHost();
String port = esearchProperties.getPort();
RestClientBuilder builder;
if (CharSequenceUtil.isNotBlank(host) && CharSequenceUtil.isBlank(port)) {
builder = RestClient.builder(HttpHost.create(host));
}else {
builder = RestClient.builder(new HttpHost(host, Integer.parseInt(port)));
}
// 异步httpclient连接延时配置
builder.setRequestConfigCallback(requestConfigBuilder -> {
requestConfigBuilder.setConnectTimeout(esearchProperties.getConnectTimeOut());
requestConfigBuilder.setSocketTimeout(esearchProperties.getSocketTimeOut());
requestConfigBuilder.setConnectionRequestTimeout(esearchProperties.getConnectionRequestTimeOut());
return requestConfigBuilder;
});
// 异步httpclient连接数配置
builder.setHttpClientConfigCallback(httpClientBuilder -> {
httpClientBuilder.setMaxConnTotal(esearchProperties.getMaxConnectNum());
httpClientBuilder.setMaxConnPerRoute(esearchProperties.getMaxConnectPerRoute());
httpClientBuilder.setDefaultCredentialsProvider(esearchProperties.getCredentialsProvider());
return httpClientBuilder;
});
return new RestHighLevelClient(builder);
}
@Bean
@ConditionalOnMissingBean
public ElasticsearchUtilTemplate elasticsearchUtilTemplate(RestHighLevelClient esRestClient, ElasticsearchProperties elasticsearchProperties) {
if (esRestClient == null) {
throw new NullPointerException("RestHighLevelClient init Error");
}
return new ElasticsearchUtilTemplate(esRestClient,elasticsearchProperties.getSearchRequestTimeOut());
}
}
装配要生效需要ElasticsearchUtilAutoConfiguration加入springboot的自动装配文件spring.factories
这是spring配置的特定目录文件,自己新建一个,名字和目录要一致
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.demo.sdk.elasticsearch.config.ElasticsearchUtilAutoConfiguration
import cn.hutool.json.JSONUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.page.PageMethod;
import com.demo.sdk.elasticsearch.exception.ElasticsearchErrorException;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
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.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
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.client.core.CountRequest;
import org.elasticsearch.client.core.CountResponse;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* ES搜索引擎模板
* @author ppp
* @date 2023/3/21
*/
public class ElasticsearchUtilTemplate {
private final RestHighLevelClient esRestClient;
private final long searchRequestTimeOut;
public ElasticsearchUtilTemplate(RestHighLevelClient esRestClient, long searchRequestTimeOut) {
this.searchRequestTimeOut = searchRequestTimeOut;
this.esRestClient = esRestClient;
}
/**
* 列表查询
*
* @param searchSourceBuilder SearchSourceBuilder
* @param clazz 返回结果class对象
* @param indices ES索引
* @return java.util.List 对象列表
*/
public <T> List<T> listSearch(SearchSourceBuilder searchSourceBuilder, Class<T> clazz, String... indices) {
Page<T> resultPage = PageMethod.getLocalPage();
boolean isResultPage = resultPage != null;
if (isResultPage) {
PageMethod.clearPage();
searchSourceBuilder.from((int) resultPage.getStartRow());
searchSourceBuilder.size(resultPage.getPageSize());
}
if (isResultPage && resultPage.isCount()) {
resultPage.setTotal(count(searchSourceBuilder, indices));
}
SearchResponse searchResponse = search(searchSourceBuilder, indices);
List<T> resultList = formatSearchResult(searchResponse, clazz);
if (isResultPage && resultPage.isCount()) {
resultPage.addAll(resultList);
return resultPage;
}
return resultList;
}
public SearchResponse search(SearchSourceBuilder searchSourceBuilder, String... indices) {
SearchRequest searchRequest = new SearchRequest(indices);
searchSourceBuilder.timeout(TimeValue.timeValueMillis(searchRequestTimeOut));
searchRequest.source(searchSourceBuilder);
return search(searchRequest);
}
public SearchResponse search(SearchRequest searchRequest) {
try {
return esRestClient.search(searchRequest, RequestOptions.DEFAULT);
} catch (Exception e) {
throw new ElasticsearchErrorException(e.getMessage(), e.getCause());
}
}
/**
* 统计数量
*
* @param searchSourceBuilder SearchSourceBuilder
* @param indices ES索引
* @return CountResponse
*/
public long count(SearchSourceBuilder searchSourceBuilder, String... indices) {
CountRequest countRequest = new CountRequest(indices);
searchSourceBuilder.timeout(TimeValue.timeValueMillis(searchRequestTimeOut));
countRequest.query(searchSourceBuilder.query());
return count(countRequest, RequestOptions.DEFAULT).getCount();
}
public CountResponse count(CountRequest countRequest, RequestOptions options) {
try {
return esRestClient.count(countRequest, options);
} catch (Exception e) {
throw new ElasticsearchErrorException(e.getMessage(), e.getCause());
}
}
/**
* 创建索引
*
* @param createIndexRequest CreateIndexRequest
* @return CreateIndexResponse
*/
public CreateIndexResponse createIndices(CreateIndexRequest createIndexRequest) {
try {
return esRestClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
} catch (Exception e) {
throw new ElasticsearchErrorException(e.getMessage(), e.getCause());
}
}
/**
* 删除索引(谨慎操作,索引下所有数据都将清空)
*
* @param index 索引名称
* @return AcknowledgedResponse
*/
public AcknowledgedResponse deleteIndex(String index) {
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest();
deleteIndexRequest.indices(index);
return deleteIndices(deleteIndexRequest);
}
/**
* 删除索引(谨慎操作,索引下所有数据都将清空)
*
* @param deleteIndexRequest DeleteIndexRequest
* @return AcknowledgedResponse
*/
public AcknowledgedResponse deleteIndices(DeleteIndexRequest deleteIndexRequest) {
try {
return esRestClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
} catch (Exception e) {
throw new ElasticsearchErrorException(e.getMessage(), e.getCause());
}
}
/**
* 插入数据
*
* @param index 索引
* @param id 唯一id
* @param source 插入对象
* @return IndexResponse
*/
public IndexResponse add(String index, Object id, Object source) {
IndexRequest indexRequest = new IndexRequest(index).id(String.valueOf(id));
indexRequest.source(JSONUtil.toJsonStr(source), XContentType.JSON);
try {
return esRestClient.index(indexRequest, RequestOptions.DEFAULT);
} catch (Exception e) {
throw new ElasticsearchErrorException(e.getMessage(), e.getCause());
}
}
/**
* 批量插入数据
* 建议:数量控制在5000以内
*
* @param index 索引
* @param sourceMap 数据<唯一id,对象>
* @return BulkResponse
*/
public BulkResponse addBulk(String index, Map<String, Object> sourceMap) {
BulkRequest request = new BulkRequest();
sourceMap.forEach((id, source) -> {
request.add(new IndexRequest(index).id(id).source(JSONUtil.toJsonStr(source), XContentType.JSON));
});
try {
return esRestClient.bulk(request, RequestOptions.DEFAULT);
} catch (Exception e) {
throw new ElasticsearchErrorException(e.getMessage(), e.getCause());
}
}
/**
* 获取数据
*
* @param getRequest GetRequest
* @return GetResponse
*/
public GetResponse get(GetRequest getRequest) {
try {
return esRestClient.get(getRequest, RequestOptions.DEFAULT);
} catch (Exception e) {
throw new ElasticsearchErrorException(e.getMessage(), e.getCause());
}
}
/**
* 更新数据
*
* @param updateRequest UpdateRequest
* @return UpdateResponse
*/
public UpdateResponse update(UpdateRequest updateRequest) {
try {
return esRestClient.update(updateRequest, RequestOptions.DEFAULT);
} catch (Exception e) {
throw new ElasticsearchErrorException(e.getMessage(), e.getCause());
}
}
/**
* 删除数据
*
* @param deleteRequest DeleteRequest
* @return DeleteResponse
*/
public DeleteResponse delete(DeleteRequest deleteRequest) {
try {
return esRestClient.delete(deleteRequest, RequestOptions.DEFAULT);
} catch (Exception e) {
throw new ElasticsearchErrorException(e.getMessage(), e.getCause());
}
}
/**
* 格式化搜索结果
*
* @param searchResponse 搜索结果
* @param clazz 返回对象
* @return java.util.List
*/
public <T> List<T> formatSearchResult(SearchResponse searchResponse, Class<T> clazz) {
SearchHit[] searchHits = searchResponse.getHits().getHits();
List<T> resultList = new ArrayList<T>();
for (SearchHit searchHit : searchHits) {
resultList.add(JSONUtil.toBean(searchHit.getSourceAsString(), clazz));
}
return resultList;
}
}
/**
* 错误异常
* @author ppp
* @date 2023/3/21
*/
public class ElasticsearchErrorException extends RuntimeException {
public ElasticsearchErrorException(String message) {
super(message);
}
public ElasticsearchErrorException(String message, Throwable cause) {
super(message, cause);
}
}
# elasticsearch
elasticsearch.config:
host: 127.0.0.1
port: 9200
username: admin
password: admin123
connect-time-out: 1000
socket-time-out: 30000
connection-request-time-out: 500
search-request-time-out: 5000
max-connect-num: 100
max-connect-per-route: 100
class DemoApplicationTests {
/**
* 获取ElasticsearchUtilTemplate模板
*/
@Autowired
private ElasticsearchUtilTemplate elasticsearchTemplate;
/**
* 分页查询
*/
@Test
void getListPage() {
// 分页
PageHelper.startPage(1, 10);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
// 筛选
boolQueryBuilder.filter(QueryBuilders.termQuery("ip", "192.168.0.1"));
// 筛选多个值 类似mysq termsQuery和termQuery区别
boolQueryBuilder.filter(QueryBuilders.termsQuery("name", Arrays.asList("张三","李四"));
// 模糊
boolQueryBuilder.must(QueryBuilders.wildcardQuery("ext1", "*测试*"));
searchSourceBuilder.query(boolQueryBuilder);
// 排序
searchSourceBuilder.sort("createTime", SortOrder.DESC);
List logIndexList = this.elasticsearchTemplate.listSearch(searchSourceBuilder, StudyLogIndex.class, index);
PageInfo studyLogIndexPageInfo = new PageInfo<>(logIndexList);
System.out.println(JSONUtil.toJsonStr(studyLogIndexPageInfo));
}
/**
* 统计
*/
@Test
void countTest() {
// 分页
PageHelper.startPage(1, 10);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
// 筛选
boolQueryBuilder.filter(QueryBuilders.termQuery("ip", "127.0.0.1"));
// 模糊
boolQueryBuilder.must(QueryBuilders.wildcardQuery("ext2", "*用*"));
searchSourceBuilder.query(boolQueryBuilder);
CountResponse count = elasticsearchTemplate.count(searchSourceBuilder, index);
System.out.println("统计总数:"+ count.getCount());
}
/**
* 删除索引
*/
@Test
void deleteIndicesTest() {
elasticsearchTemplate.deleteIndex(index);
}
/**
* 创建es索引
*/
@Test
void createIndicesTest() {
CreateIndexRequest createIndexRequest = new CreateIndexRequest(index);
createIndexRequest.mapping("{\n" +
" \"properties\": {\n" +
" \"globalId\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"site\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"tag\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"uid\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"classId\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"courseId\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"videoId\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"startTime\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"time\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"ip\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"start\": {\n" +
" \"type\": \"integer\"\n" +
" },\n" +
" \"end\": {\n" +
" \"type\": \"integer\"\n" +
" },\n" +
" \"createTime\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"ext1\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"ext2\": {\n" +
" \"type\": \"keyword\"\n" +
" }\n" +
" }\n" +
"}", XContentType.JSON);
elasticsearchTemplate.createIndices(createIndexRequest);
}
/**
* 插入es数据
*/
@Test
void addDataTest() {
for (int i = 0; i < 10; i++) {
StudyLogIndex studyLogIndex = new StudyLogIndex();
studyLogIndex.setGlobalId("CX"+i);
studyLogIndex.setSite("CX");
studyLogIndex.setTag("SUCCESS");
studyLogIndex.setUid(12000000L+i);
studyLogIndex.setClassId(123456L);
studyLogIndex.setCourseId(123456L);
studyLogIndex.setVideoId(123456L);
studyLogIndex.setStartTime(123456L);
studyLogIndex.setTime(123456L);
studyLogIndex.setIp("127.0.0.1");
studyLogIndex.setStart(0);
studyLogIndex.setEnd(0);
studyLogIndex.setCreateTime(0L);
studyLogIndex.setExt1("测试es工具");
studyLogIndex.setExt2("备用");
elasticsearchTemplate.add(index, studyLogIndex.getGlobalId(), studyLogIndex);
}
}
/**
* 批量插入es
*/
@Test
void bulkAddDataTest() {
Map map = new HashMap<>(16);
for (int i = 100; i < 1000; i++) {
StudyLogIndex studyLogIndex = new StudyLogIndex();
studyLogIndex.setGlobalId(IdUtil.getSnowflakeNextIdStr());
studyLogIndex.setSite("ZJ");
studyLogIndex.setTag("SUCCESS");
studyLogIndex.setUid(12000000L+i);
studyLogIndex.setClassId(123456L);
studyLogIndex.setCourseId(123456L);
studyLogIndex.setVideoId(123456L);
studyLogIndex.setStartTime(123456L);
studyLogIndex.setTime(123456L);
studyLogIndex.setIp("192.168.0.3");
studyLogIndex.setStart(0);
studyLogIndex.setEnd(0);
studyLogIndex.setCreateTime(0L);
studyLogIndex.setExt1("批量测试es工具");
studyLogIndex.setExt2("备用");
map.put(studyLogIndex.getGlobalId(), studyLogIndex);
}
elasticsearchTemplate.addBulk(index, map);
}
/**
* 聚合检索
*/
@Test
void aggregateTest() {
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 聚合检索不设置大小会默认只返回10个统计结果
TermsAggregationBuilder field = AggregationBuilders.terms("group_by_ip").field("ip").size(1000);
searchSourceBuilder.aggregation(field).size(10);
SearchResponse search = elasticsearchTemplate.search(searchSourceBuilder, index);
System.out.println(JSONUtil.toJsonStr(search));
Map countMap = AggregationsUtil.getCountMap(search.getAggregations());
System.out.println(JSONUtil.toJsonStr(countMap));
}
}