为什么写这篇文章
- 网上大量关于 jpa + mysql 动态条件查询的博客,但缺少 jpa + es 动态条件查询博客,找到的都是质量不高的文章,不能真正跑通
- 如果不用动态条件查询,当有多个条件进行查询时就非常麻烦,例如有 4 个参数,则一共要写 4 * 3 * 2 * 1 查询语句
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.3.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<version>2.3.12.RELEASE</version>
</dependency>
实体类
package cn.xxx.api.project.dal.es.dataobject;
import lombok.Data;
import lombok.ToString;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import org.springframework.data.elasticsearch.annotations.GeoPointField;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
@Data
@Document(indexName = "user_index")
@ToString
public class EsUserDO {
@Id
private Long id;
@Field(type = FieldType.Long)
private Long appId;
/** 用户昵称 */
@Field(type = FieldType.Keyword)
private String name;
@Field(type = FieldType.Keyword)
private String sex;
@Field(type = FieldType.Boolean)
private Boolean available;
}
DAO
package cn.xxx.api.project.dal.es.dao;
import cn.xxx.api.project.dal.es.dataobject.EsUserDO;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface EsUserDAO extends ElasticsearchRepository<EsUserDO, Long> {
}
动态条件查询
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
/**
* es 动态条件查询用户信息
*
* @param appId 应用ID
* @param name 用户名
* @param sex 性别
* @param available 是否可用
* @param page 第几页(从 1 开始)
* @param size 每页条数
* @return
*/
public Page<EsUserDO> searchUsers(Long appId, String name, String sex, Boolean available, Integer page, Integer size) {
log.debug("searchUsers-start appId : {} name : {} sex : {} available : {} page : {} size : {}"
, appId, name, sex, available, sex, page, size);
Pageable pageable = PageRequest.of(page - 1, size);
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
if (Objects.nonNull(appId)) {
boolQuery.must(QueryBuilders.termQuery("appId", appId));
}
if (StringUtils.isNotEmpty(name)) {
boolQuery.must(QueryBuilders.termQuery("name", name));
}
if (StringUtils.isNotEmpty(sex)) {
boolQuery.must(QueryBuilders.termQuery("sex", sex));
}
if (Objects.nonNull(available)) {
if (available) {
boolQuery.must(QueryBuilders.termQuery("available", available));
} else {
// 查询 available 为 false 或者不存在该字段的数据
BoolQueryBuilder shouldQuery = QueryBuilders.boolQuery()
.should(QueryBuilders.termQuery("available", available))
.should(QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery("available")));
boolQuery.must(shouldQuery);
}
}
Page<EsUserDO> search = esUserDAO.search(boolQuery, pageable);
log.info("searchUsers-end boolQuery : {} search : {}", boolQuery.toString(), JSON.toJSONString(search));
return search;
}