JPA + ES 动态条件查询

为什么写这篇文章

  • 网上大量关于 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;
}

你可能感兴趣的:(ES,elasticsearch,大数据,搜索引擎)