文章目录
- Elasticsearch
- 需求
- 使用版本
- 联合索引多条件查询示例
- 相关API
- 相关资料
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