elasticsearch 跨索引联合多条件查询

2023-04-06 09:26:52 浏览数 (1)

文章目录
  • 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

联合索引多条件查询示例

代码语言:javascript复制
@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();
    }
}
代码语言:javascript复制
//检测每个索引是否存在,只返回存在的索引
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

代码语言:javascript复制
//查看索引结构
GET : http://127.0.0.1:9200/索引/_mapping

0 人点赞