es增删改查常用语法
我们日常开发中,操作数据库写sql倒是不可能忘记,但是操作es的dsl语句有时候很容易忘记,特地记录一下方便查找。
注意,如果有些字段设置的text类型,那么在查询的时候加上.keyword,比如查询code字段
{ "query": { "terms": { "code.keyword": ["aaa","bbb"] } } }
DSL语句
1、创建索引
-- 创建索引 PUT /my_index { "mappings": { "properties": { "title": { "type": "text" }, "description": { "type": "text" }, "timestamp": { "type": "date" } } } }
2、插入文档
-- 插入文档 POST /my_index/_doc/主键值 { "title": "Sample Document", "description": "This is a sample document for Elasticsearch", "timestamp": "2022-01-01" }
3、更新文档
-- 更新一个文档 POST /my_index/_update/1 // 主键 { "doc": { "字段1": "内容1", "字段2": "内容2", "字段3": "内容3" // 添加需要更新的多个字段及对应的内容 } } -- 批量更新多个文档字段 POST /my_index/_update_by_query { "query": { "terms": { "_id": [111, 222] // 指定id为111和222的文档 }, "script": { "source": "ctx._source.aaa= 1; ctx._source.bbb= 2" // 更新aaa和bbb字段为1和2 } } -- 批量更新多个文档字,指定字段内容为另外一个字段的内容 POST /search_order_index/_update_by_query { "query": { "terms": { "orderNo": [ "1111", // 指定更新订单编号为111和222的记录 "222" ] } }, "script": { "source": " ctx._source.字段1= 1; // 指定字段1 为1 ctx._source.字段2= 1; // 指定字段2 为1 ctx._source.字段3= 0; // 指定字段3为0 ctx._source.字段4= ctx._source.字段5" // 指定字段4为字段5的内容 } } -- 更新所有文档字段 POST /my_index/_update_by_query { "query": { "match_all": {} // 匹配所有文档 }, "script": { "source": "ctx._source.aaa = 1; ctx._source.bbb = 1" // 批量更新aaa和bbb字段为1 } }
4、删除文档(单独、多个、全部)
-- 删除单条文档 DELETE /my_index/_doc/主键值 或者 -- 删除单条文档 POST 索引名/_delete_by_query { "query":{ "term":{ "_id":4043 } } } -- 删除多条文档 POST 索引名/_delete_by_query { "query": { "terms": { "_id": [4043, 4044, 4045] // 添加多个id值 } } } -- 删除索引中的所有数据 POST my_index/_delete_by_query { "query": { "match_all": { } } }
5、删除索引
-- 删除索引 DELETE /my_index
6、设置索引别名
-- 设置索引别名 POST /_aliases { "actions": [ {"add": {"index": "my_index2", "alias": "my_index"}} ] }
7、设置切片和副本数量
-- 设置切片和副本数量 PUT your_index { "mappings" : { "properties" : { #索引字段(略) } } "settings" : { "number_of_shards" : 3, "number_of_replicas" : 1 } }
8、查询
-- 查询单个字段内容 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" } } ] }
9、统计
POST /my_index/_count { "query": { "bool": { "must": { "term": { "messageId": "CS202303160008-2" } } } } }
代码
pom依赖
4.0.0com.demo.sdkelasticsearch-util1.0.0-SNAPSHOTjarelasticsearch-utilSpring Boot Support for elasticsearch-util117.10.02.7.05.8.151.4.2org.springframework.bootspring-boot-autoconfigure${spring-boot.version}org.springframework.bootspring-boot-configuration-processor${spring-boot.version}trueorg.springframework.bootspring-boot-starter-logging${spring-boot.version}org.elasticsearch.clientelasticsearch-rest-high-level-client${elasticsearch.version}com.github.pagehelperpagehelper-spring-boot-starter${pagehelper.version}cn.hutoolhutool-all${hutool.version}org.apache.maven.pluginsmaven-compiler-plugin3.8.11111UTF-8org.apache.maven.pluginsmaven-source-plugintruecompilejar
1、ES配置类
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; } }
2、ES工具自动配置类
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()); } }
3、自动装配配置
装配要生效需要ElasticsearchUtilAutoConfiguration加入springboot的自动装配文件spring.factories
这是spring配置的特定目录文件,自己新建一个,名字和目录要一致
# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration= com.demo.sdk.elasticsearch.config.ElasticsearchUtilAutoConfiguration
4、定义一个模板工具类
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 List listSearch(SearchSourceBuilder searchSourceBuilder, Class clazz, String... indices) { Page 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 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 数据 * @return BulkResponse */ public BulkResponse addBulk(String index, Map 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 List formatSearchResult(SearchResponse searchResponse, Class clazz) { SearchHit[] searchHits = searchResponse.getHits().getHits(); List resultList = new ArrayList(); for (SearchHit searchHit : searchHits) { resultList.add(JSONUtil.toBean(searchHit.getSourceAsString(), clazz)); } return resultList; } }
5、定义一个异常
/** * 错误异常 * @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); } }
6、application.yml配置
# 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
7、测试
class DemoApplicationTests { /** * 获取ElasticsearchUtilTemplate模板 */ @Autowired private ElasticsearchUtilTemplate elasticsearchTemplate; /** * 分页查询 */ @Test void getListPage() { // 分页 PageHelper.startPage(1, 10); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); // 筛选 filter比must要好一点,filter会对条件进行缓存,这有助于提高查询性能,特别是对于频繁使用的过滤条件 boolQueryBuilder.filter(QueryBuilders.termQuery("ip", "192.168.0.1")); // 筛选多个值 类似mysql的in效果 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 map = new HashMap(16); for (int i = 100; i countMap = AggregationsUtil.getCountMap(search.getAggregations()); System.out.println(JSONUtil.toJsonStr(countMap)); } }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持IT俱乐部。