Elasticsearch
Elasticsearch 是一个免费且开放的分布式搜索和分析引擎。适用于包括文本、数字、地理空间、结构化和非结构化数据等在内的所有类型的数据。Elasticsearch 在 Apache Lucene 的基础上开发而成,以其简单的 REST 风格 API、分布式特性、速度和可扩展性而闻名,是 Elastic Stack 的核心组件;Elastic Stack 是一套适用于数据采集、扩充、存储、分析和可视化的免费开源工具。人们通常将 Elastic Stack 称为 ELK Stack(代指 Elasticsearch、Logstash 和 Kibana),目前 Elastic Stack 包括一系列丰富的轻量型数据采集代理,这些代理统称为 Beats,可用来向 Elasticsearch 发送数据。
Elasticsearch 用来收集大量日志和检索文本是个不错的选择,可以在承载了 PB 级数据的成百上千台服务器上运行。
关键字:
- 实时
- 分布式
- 搜索
- 分析
需求
如果既要对一些字段进行分词查询,同时要对另一些字段进行精确查询,就需要使用布尔查询来实现了。同时索引是按照一定规则建立的,例如按照时间段,此时查询的时候会涉及到联合索引查询。布尔查询对应于Lucene的BooleanQuery查询,实现将多个查询组合起来,有三个可选的参数:
must: 文档必须匹配must所包括的查询条件,相当于 “AND”
should: 文档应该匹配should所包括的查询条件其中的一个或多个,相当于 “OR”
must_not: 文档不能匹配must_not所包括的该查询条件,相当于“NOT”
使用版本
elasticsearch:7.1.1
spring-boot-starter-data-elasticsearch:2.5.4
联合索引多条件查询示例
@Autowired private RestHighLevelClient client; ObjectMapper mapper = new ObjectMapper(); @Override public Page<Book> search(Pageable pageable, Set<String> indexNameList) { BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery(); //must中的条件,必须全部匹配。需要将字段的type设置为keyword 或者 指定字段时用 `字段.keyword`(实际测试并不生效,可能还和analyzer有关) queryBuilder.must(QueryBuilders.termQuery("title", "杨")); //匹配should中的条件(匹配1个或多个,根据需求配置) queryBuilder.should(QueryBuilders.termQuery("address", "山西")); //matchPhraseQuery 通配符搜索查询,支持 * 和 ?, ?匹配任意单个字符,这么查询可能慢 queryBuilder.must(QueryBuilders.matchPhraseQuery("remark", "*" + "你好" + "*")); //必须匹配的 should条件数量 queryBuilder.minimumShouldMatch(1); //数据集合 List<Book> hits = new ArrayList<>(); //总数 long total = 0L; SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder() .query(queryBuilder) .from(pageable.getPageNumber()) .size(pageable.getPageSize()); //es中存在的索引 List<String> arrayList = getExistIndex(indexNameList); SearchRequest searchRequest = new SearchRequest(indexArray).source(searchSourceBuilder); try { SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); // 搜索结果 org.elasticsearch.search.SearchHits searchHits = searchResponse.getHits(); // 匹配到的总记录数 total = searchHits.getTotalHits().value; org.elasticsearch.search.SearchHit[] searchHitsHits = searchHits.getHits(); for (SearchHit searchHitsHit : searchHitsHits) { //如果es中字段比定义的实体类中多,反序列化会提示异常,需要加以下注解 //忽略无法识别的属性:@JsonIgnoreProperties(ignoreUnknown = true) Book book = mapper.readValue(searchHitsHit.getSourceRef().utf8ToString(), Book.class); hits.add(book); } } catch (IOException e) { e.printStackTrace(); } }
//检测每个索引是否存在,只返回存在的索引 private List<String> getExistIndex(Set<String> indexNameList) { List<String> existsIndex = new ArrayList<>(); for (String indexName : indexNameList) { try { GetIndexRequest existsRequest = new GetIndexRequest(); existsRequest.indices(indexName); boolean exists = client.indices().exists(existsRequest, RequestOptions.DEFAULT); //返回索引集合中存在的索引,避免传入不存在的索引,导致查询异常 if (exists) { existsIndex.add(indexName); } } catch (Exception e) { } } return existsIndex; }
相关API
//查看索引结构 GET : http://127.0.0.1:9200/索引/_mapping
相关资料
https://blog.csdn.net/u011821334/article/details/100979286
https://www.cnblogs.com/coderxz/p/13268417.html
https://www.cnblogs.com/keatsCoder/p/11341835.html
https://blog.csdn.net/weixin_43847283/article/details/123616890
https://blog.csdn.net/weixin_43847283/article/details/123933244