elasticsearch8.5.0 复杂查询-Java API Client

2,498 阅读3分钟

组合查询


/**
     * 组合查询user,user中包含userName、age、sex属性等.
     *
     * @param indexName 索引名称
     * @param user 查询dto
     * @return 查询到的user集合
     */		
public List<User> queryUser(String indexName, UserDTO user) {
    // 将多个查询条件放入list中.
	List<Query> queries = new ArrayList<>();
	Query bySex = this.initMatchQuery("sex", user.getSex());
	Query byAge = this.initRangeQuery("age", 18, 25);
	queries.add(bySex);
	queries.add(byAge);
    try {
        // 从es中根据条件查询结果.
        SearchResponse<User> searchResponse = client.search(s -> s
                                .index(indexName)
                                .query(q -> q
                                        .bool(b -> b.must(queries)
                                        )
                                ), User.class);
        List<Hit<User>> hitList = searchResponse.hits().hits();
        List<User> userList = new ArrayList<>();
        for (Hit<User> mapHit : hitList) {
            userList.add(mapHit.source());
        }
        return userList;
    }catch (Exception e) {
            throw new RunExcepotion("【查询 -> 失败】从es中组合查询user出错,错误信息为:{}", e.getMessage());
    }

}


/**
 * match查询语句.
 *
 * @param fieldName 查询字段名称
 * @param fieldValue 查询字段值
 * @return query语句
 */
private Query initMatchQuery(String fieldName, String fieldValue) {
    return StringUtils.isNotBlank(fieldValue) ? MatchQuery.of(m -> m
            .field(fieldName + ".keyword")
            .query(fieldValue)
    )._toQuery() : null;
}

/**
 * range查询语句.
 *
 * @param fieldName 查询字段名称
 * @param begin 开始时间
 * @param end 结束时间
 * @return query语句
 */

private Query initRangeQuery(String fieldName, Integer begin, Integer end) {
    return  RangeQuery.of(m -> m
            .field(fieldName + ".keyword")
            .gte((JsonData.of(begin)))
            .lte((JsonData.of(end)))
    )._toQuery();
}

 

组合+分页 查询

/**
 * 组合查询user,user中包含userName、age、sex属性等.
 *
 * @param indexName 索引名称
 * @param user 查询dto
 * @return 查询到的user分页数据
 */		
public PageVO queryUser(String indexName, UserDTO user) {
    // 将多个查询条件放入list中.
	List<Query> queries = new ArrayList<>();
	Query bySex = this.initMatchQuery("sex", user.getSex());
	Query byAge = this.initRangeQuery("age", 18, 60);
	queries.add(bySex);
	queries.add(byAge);
	int offSet = user.getOffset();
	// 因为es分页时,查找的是from到from+size的数据.
    Integer from = offSet <= 0 ? 0 : apuserpLog.getLimit() * offSet;
    try {
        // 从es中根据条件查询结果.
        SearchResponse<User> searchResponse = client.search(s -> s
                                .index(indexName)
                                .query(q -> q
                                        .bool(b -> b.must(queries)
                                        )
                                .from(from)
                                .size(user.getLimit())
                                ), User.class);
        List<Hit<User>> hitList = searchResponse.hits().hits();
        List<User> userList = new ArrayList<>();
        for (Hit<User> mapHit : hitList) {
            userList.add(mapHit.source());
        }
        long total = searchResponse.hits().total() != null ? searchResponse.hits().total().value() : 0;
        return new PageVO().setContent(userList)
                    .setSize(user.getLimit())
                    .setTotalElements(total)
                    .setTotalPages((total + user.getLimit() - 1) / user.getLimit());
    }catch (Exception e) {
            throw new RunExcepotion("【查询 -> 失败】从es中组合查询user出错,错误信息为:{}", e.getMessage());
    }

}

组合+分页+排序查询

/**
 * 组合查询user,user中包含userName、age、sex属性等.
 *
 * @param indexName 索引名称
 * @param user 查询dto
 * @return 查询到的user分页数据
 */		
public PageVO queryUser(String indexName, UserDTO user) {
    // 将多个查询条件放入list中.
	List<Query> queries = new ArrayList<>();
	Query bySex = this.initMatchQuery("sex", user.getSex());
	Query byAge = this.initRangeQuery("age", 18, 60);
	queries.add(bySex);
	queries.add(byAge);
	int offSet = user.getOffset();
	// 因为es分页时,查找的是from到from+size的数据.
    Integer from = offSet <= 0 ? 0 : apuserpLog.getLimit() * offSet;
    try {
        // 从es中根据条件查询结果.
        SearchResponse<User> searchResponse = client.search(s -> s
                                .index(indexName)
                                .query(q -> q
                                        .bool(b -> b.must(queries)
                                        )
                                .from(from)
                                .size(user.getLimit())
                                // 按照创建时间正序排列.
                                .sort(sort -> sort.field(f -> f.field("createTime.keyword").order(SortOrder.Asc)))
                                ), User.class);
        List<Hit<User>> hitList = searchResponse.hits().hits();
        List<User> userList = new ArrayList<>();
        for (Hit<User> mapHit : hitList) {
            userList.add(mapHit.source());
        }
        long total = searchResponse.hits().total() != null ? searchResponse.hits().total().value() : 0;
        return new PageVO().setContent(userList)
                    .setSize(user.getLimit())
                    .setTotalElements(total)
                    .setTotalPages((total + user.getLimit() - 1) / user.getLimit());
    }catch (Exception e) {
            throw new RunExcepotion("【查询 -> 失败】从es中组合查询user出错,错误信息为:{}", e.getMessage());
    }

}

组合+分页+排序+分组 查询

/**
 * 组合查询user,user中包含userName、age、sex、education属性等.
 *
 * @param indexName 索引名称
 * @param user 查询dto
 * @return 查询到的user分页数据
 */		
public PageVO queryUser(String indexName, UserDTO user) {
    // 将多个查询条件放入list中.
	List<Query> queries = new ArrayList<>();
	Query byEducation = this.initMatchQuery("education", user.getEducation());
	Query byAge = this.initRangeQuery("age", 18, 60);
	queries.add(byEducation);
	queries.add(byAge);
	int offSet = user.getOffset();
	// 因为es分页时,查找的是from到from+size的数据.
    Integer from = offSet <= 0 ? 0 : apuserpLog.getLimit() * offSet;
    try {
    
        // 根据性别分组展示,且分组内只展示年龄最大的一条.
        List<SortOptions> sorts = new ArrayList<>();
        SortOptions sortName = SortOptionsBuilders.field(f -> f.field("age.keyword")
                .order(SortOrder.Desc));
        sorts.add(sortName);
        // 从es中根据条件查询结果.
        SearchResponse<User> searchResponse = client.search(s -> s
                                .index(indexName)
                                .query(q -> q
                                        .bool(b -> b.must(queries)
                                        )
                                .collapse(col -> col
                                        .field("sex.keyword").innerHits(inner -> inner
                                                .name("group")
                                                .ignoreUnmapped(true)
                                                .from(0)
                                                .size(0)
                                                .sort(sorts)
                                        ))
                                .from(from)
                                .size(user.getLimit())
                                // 按照创建正序排列.
                                .sort(sort -> sort.field(f -> f.field("createTime.keyword").order(SortOrder.Asc)))
                                ), User.class);
        List<Hit<User>> hitList = searchResponse.hits().hits();
        List<User> userList = new ArrayList<>();
        for (Hit<User> mapHit : hitList) {
            userList.add(mapHit.source());
        }
        // 这里的总数其实还是未分组的数据,collapse只是相当于把相同的数据折叠了,要解决该问题可以看下一个加上聚合的操作.
        long total = searchResponse.hits().total() != null ? searchResponse.hits().total().value() : 0;
        return new PageVO().setContent(userList)
                    .setSize(user.getLimit())
                    .setTotalElements(total)
                    .setTotalPages((total + user.getLimit() - 1) / user.getLimit());
    }catch (Exception e) {
            throw new RunExcepotion("【查询 -> 失败】从es中组合查询user出错,错误信息为:{}", e.getMessage());
    }

}

组合+分页+排序+分组+聚合 查询

/**
 * 组合查询user,user中包含userName、age、sex、education属性等.
 *
 * @param indexName 索引名称
 * @param user 查询dto
 * @return 查询到的user分页数据
 */		
public PageVO queryUser(String indexName, UserDTO user) {
    // 将多个查询条件放入list中.
	List<Query> queries = new ArrayList<>();
	Query byEducation = this.initMatchQuery("education", user.getEducation());
	Query byAge = this.initRangeQuery("age", 18, 60);
	queries.add(byEducation);
	queries.add(byAge);
	int offSet = user.getOffset();
	// 因为es分页时,查找的是from到from+size的数据.
    Integer from = offSet <= 0 ? 0 : apuserpLog.getLimit() * offSet;
    try {
    
        // 根据性别分组展示,且分组内只展示年龄最大的一条.
        List<SortOptions> sorts = new ArrayList<>();
        SortOptions sortName = SortOptionsBuilders.field(f -> f.field("age.keyword")
                .order(SortOrder.Desc));
        sorts.add(sortName);
        // 从es中根据条件查询结果.
        SearchResponse<User> searchResponse = client.search(s -> s
                                .index(indexName)
                                .query(q -> q
                                        .bool(b -> b.must(queries)
                                        )
                                // 根据sex性别进行分组.
                                .collapse(col -> col
                                        .field("sex.keyword").innerHits(inner -> inner
                                                .name("group")
                                                .ignoreUnmapped(true)
                                                .from(0)
                                                .size(0)
                                                .sort(sorts)
                                        ))
                                // 根据sex性别进行聚合.
                                .aggregations("sex.keyword", a -> a.terms(t -> t.field("sex.keyword")
                                        .size(100000)))
                                .from(from)
                                .size(user.getLimit())
                                // 按照创建正序排列.
                                .sort(sort -> sort.field(f -> f.field("createTime.keyword").order(SortOrder.Asc)))
                                ), User.class);
        List<Hit<User>> hitList = searchResponse.hits().hits();
        List<User> userList = new ArrayList<>();
        for (Hit<User> mapHit : hitList) {
            userList.add(mapHit.source());
        }
        long total = searchResponse.hits().total() != null ? searchResponse.hits().total().value() : 0;
        
        Map<String, Long> map = new HashMap<>();
        searchResponse.aggregations().get("sex.keyword").sterms().buckets().array()
                .forEach(f -> map.put(f.key().stringValue(), f.docCount()));
        // 这里total改成实际的分组数据.
        total = map.size();
        // 这里将每一个分组出现的次数也进行了统计.
        userList.forEach(user -> {
            if (map.containsKey(user.getSex())) {
                user.setCount(map.get(user.getSex()));
            }
        });
        return new PageVO().setContent(userList)
                    .setSize(user.getLimit())
                    .setTotalElements(total)
                    .setTotalPages((total + user.getLimit() - 1) / user.getLimit());
    }catch (Exception e) {
            throw new RunExcepotion("【查询 -> 失败】从es中组合查询user出错,错误信息为:{}", e.getMessage());
    }

}