基于springboot+elasticsearch整合分页和高亮查询

spring-data3.1.x整合

elasticsearch只支持到6.x,如果配置连接7.x

则会报如下错误

org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available: [{#transport#-1}{m7cqAfz-R_WtXreSiJp6GQ}{192.168.37.100}{192.168.37.100:9300}]

配置环境
1.pom文件配置

这里使用的2.1.6.RELEASE的springboot,对应3.1.9.RELEASE的spring-data-elasticsearch

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-elasticsearch</artifactId>

2.yml配置文件配置

spring:

data:

elasticsearch:

    repositories:

        enabled: true

    cluster-name: elasticsearch

    cluster-nodes: localhost:9300

3.构建elasticsearch实体类

@Data

@Document(indexName = "query", type = "people_info")

public class EsQueryBean implements Serializable {

    @Id

    @Field(type = FieldType.Keyword, store = true)

    private String id;

    @Field(index = true, type = FieldType.Text, analyzer = "ik_max_word")

    private String content;

    /**

     * 身份证号

     */

    @Field(index = true, type = FieldType.Keyword)

    private String idCard;

    /**

     * 年龄

     */

    @Field(index = true, type = FieldType.Integer)

    private Integer age;

    /**

     * 性别

     */

    @Field(index = true, type = FieldType.Keyword)

    private String sex;

    /**

     * 姓名

     */

    @Field(index = true, type = FieldType.Text, analyzer = "ik_max_word")

    private String name;

}

3.创建elasticsearch查询条件辅助类

查询条件BoTermQuery生成的完整查询结构:

{

"query": {

"bool": {

"filter": [

{

"term": {}

},

{

"terms": {}

},

{

"match": {}

},

{

"multi_match": {

"fields": []

}

},

{

"range": {}

}

],

"should": [

{

"term": {}

},

{

"terms": {}

},

{

"match": {}

},

{

"multi_match": {

"fields": []

}

},

{

"range": {}

}

]

}

}

}

过滤条件类

@Data

public class BoTermQuery {

/**

* 简单条件

*/

private List<Pair<String, ?>> termConditions = new ArrayList<>();

/**

* 范围条件

*/

private Map<String, Pair<?, ?>> rangeConditions = new HashMap<>();

/**

* 查询条件

*/

private List<Pair<?, String>> matchConditions = new ArrayList<>();

/**

* should 条件

*/

private Should should;



private BoTermQuery() {



}



/**

* 添加简单条件

*

* @param field

* @param condition list或者单个数据

* @return

*/

public BoTermQuery addTermCondition(String field, Object condition) {

  Pair<String, Object> pair = new Pair<>(field, condition);

  termConditions.add(pair);

  return this;

}



/**

* 添加简单条件

*

* @param field

* @param condition list或者单个数据

* @return

*/

public BoTermQuery addTermCondition(String field, Collection<?> condition) {

  Pair<String, Object> pair = new Pair<>(field, condition);

  termConditions.add(pair);

  return this;

}



/**

* 一个值匹配多个字段

*

* @param condition

* @param fields

* @return

*/

public BoTermQuery addMatchCondition(String condition, String... fields) {

  Pair<String[], String> pair = new Pair<>(fields, condition);

  matchConditions.add(pair);

  return this;

}



/**

* 一个值匹配一个字段

*

* @param condition

* @param field

* @return

*/

public BoTermQuery addMatchCondition(String field,String condition) {

  Pair<?, String> pair = new Pair<>(field, condition);

  matchConditions.add(pair);
 
  return this;

}



/**

* 添加范围条件

*

* @param field

* @param min

* @param max

* @return

*/

public BoTermQuery addRangeCondition(String field, Object min, Object max) {

  Pair<Object, Object> pair = new Pair<>(min, max);

  rangeConditions.put(field, pair);

  return this;

}



public BoTermQuery addShouldCondition(Should should) {

  this.should = should;

  return this;

}



public static BoTermQuery create() {

  return new BoTermQuery();

}



@Data

public static class Should {

/**

* 最少匹配的个数

*/

private int minimumNumberShouldMatch = 1;

/**

* 简单条件

*/

private List<Pair<String, ?>> termConditions = new ArrayList<>();

/**

* 范围条件

*/

private Map<String, Pair<?, ?>> rangeConditions = new HashMap<>();

/**

* 查询条件

* key是field

* value是值

*/

private List<Pair<?, String>> matchConditions = new ArrayList<>();



private Should(int minimumNumberShouldMatch) {

  this.minimumNumberShouldMatch = minimumNumberShouldMatch;

}



/**

* 添加简单条件

*

* @param field

* @param condition

* @return

*/

public Should addTermCondition(String field, Object condition) {

  Pair<String, Object> pair = new Pair<>(field, condition);

  termConditions.add(pair);

  return BoTermQuery.Should.this;

}



/**

* 添加简单条件

*

* @param field

* @param condition

* @return

*/

public Should addTermCondition(String field, Collection<?> condition) {

  Pair<String, Object> pair = new Pair<>(field, condition);

  termConditions.add(pair);

  return BoTermQuery.Should.this;

}



/**

* 一个值匹配多个字段

*

* @param condition

* @param fields

* @return

*/

public Should addMatchCondition(String condition, String... fields) {

   Pair<String[], String> pair = new Pair<>(fields,    condition);

  matchConditions.add(pair);

  return this;

}



/**

* 一个值匹配一个字段

*

* @param condition

* @param field

* @return

*/

public Should addMatchCondition(String field,String        condition) {

    Pair<?, String> pair = new Pair<>(field, condition);

   matchConditions.add(pair);

   return this;

}



/**

* 添加范围条件

*

* @param field

* @param min

* @param max

* @return

*/

public Should addRangeCondition(String field, Object min, Object max) {

    Pair<Object, Object> pair = new Pair<>(min, max);

   rangeConditions.put(field, pair);

   return this;

}



public static Should create(int minimumNumberShouldMatch) {

return new Should(minimumNumberShouldMatch);

}



}

}

4.分页信息类

@Data

public class PageParam {

  private int pageNum;

  private int pageSize = 10;

}    

5.创建elasticsearch查询service类

public interface EsSearchService<T> {

/**

* 创建索引

*

* @param tClass

* @return

*/

  boolean createIndex(Class<T> tClass);



/**

* 创建索引映射

*

* @param tClass

* @return

*/

  boolean putMapping(Class<T> tClass);
 




/**

* 判断一个索引是否存在

*

* @param tClass

* @return

*/

  boolean existIndex(Class<T> tClass);



/**

* 删除索引

*

* @param tClass

* @return

*/

  boolean deleteIndex(Class<T> tClass);



/**

* 分页请求

*

* @param pageParam 分页参数

* @param boTermQuery es查询对象封装

* @param tClass 索引类

* @return 文档对象集合

*/

  List<T> queryList(PageParam pageParam, BoTermQuery boTermQuery, Class<T> tClass);



/**

* 查询高亮的分页请求

*

* @param pageParam 分页参数

* @param boTermQuery es查询对象封装

* @param highlightFields 需要高亮的字段集合

* @param indexName 索引名称

* @param tClass 索引类

* @return 文档对象集合

*/

  List<T> queryListHighlight(PageParam pageParam, BoTermQuery boTermQuery, List<String> highlightFields,

  String indexName, Class<T> tClass);

}

实现类

@Service

public abstract class EsSearchServiceImpl<T> implements EsSearchService<T> {

@Autowired

  ElasticsearchTemplate elasticsearchTemplate;



  @Override

  public boolean createIndex(Class<T> tClass) {

    return elasticsearchTemplate.createIndex(tClass);

  }



  @Override

  public boolean putMapping(Class<T> tClass) {

    return elasticsearchTemplate.putMapping(tClass);

  }





  @Override

  public boolean existIndex(Class<T> tClass) {

    return elasticsearchTemplate.indexExists(tClass);

  }



  @Override

  public boolean deleteIndex(Class<T> tClass) {

    return elasticsearchTemplate.deleteIndex(tClass);

  }



/**

* @param pageParam

* @param boTermQuery

* @param tClass

* @return

*/

  @Override

  public List<T> queryList(PageParam pageParam,  BoTermQuery boTermQuery, Class<T> tClass) {

    Pageable pageable = PageRequest.of(pageParam.getPageNum(), 
  
    pageParam.getPageSize());

    BoolQueryBuilder queryBuilder = createQueryBuilder(boTermQuery);

    SearchQuery searchQuery = new NativeSearchQueryBuilder()

     .withQuery(queryBuilder)

     .withPageable(pageable)

     .build();

    return elasticsearchTemplate.queryForPage(searchQuery, tClass).getContent();

  }



  @Override

  public List<T> queryListHighlight(PageParam pageParam, BoTermQuery boTermQuery, List<String> highlightFields, String indexName, Class<T> tClass) {

    BoolQueryBuilder queryBuilder = createQueryBuilder(boTermQuery);

    HighlightBuilder highlightBuilder = createHighlightBuilder(highlightFields);

    SearchResponse searchResponse = elasticsearchTemplate.getClient().prepareSearch(indexName)

     .setQuery(queryBuilder)

     .highlighter(highlightBuilder)

     .setFrom(pageParam.getPageNum())

     .setSize(pageParam.getPageSize())

     .get();

   SearchHits searchHits = searchResponse.getHits();

   List<T> results = new ArrayList<>();

  //组装结果

  for (SearchHit searchHit : searchHits) {

    Map<String, Object> sourceAsMap = searchHit.getSourceAsMap();

    Map<String, HighlightField> highlightFieldsResult = searchHit.getHighlightFields();

    try {

       T t = tClass.newInstance();

       Field[] declaredFields = t.getClass().getDeclaredFields();

       for (Field field : declaredFields) {

         field.setAccessible(true);

         String name = field.getName();

         if (highlightFieldsResult.get(name) != null) {

           field.set(t, (highlightFieldsResult.get(name).getFragments()[0]).toString());

         } else {

           Object fieldValue = sourceAsMap.get(name);

           field.set(t, fieldValue);

          }

        }

    results.add(t);

    } catch (Exception e) {

      e.printStackTrace();

    }

  }

  return results;

}



/**

* 构造查询器

*

* @param boTermQuery

* @return

*/

  private BoolQueryBuilder createQueryBuilder(BoTermQuery boTermQuery) {

    List<Pair<String, ?>> termConditions = boTermQuery.getTermConditions();

    Map<String, Pair<?, ?>> rangeConditions = boTermQuery.getRangeConditions();

    List<Pair<?, String>> matchConditions = boTermQuery.getMatchConditions();



    BoTermQuery.Should should = boTermQuery.getShould();

    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

    if (should != null) {

      boolQueryBuilder.minimumShouldMatch(should.getMinimumNumberShouldMatch());

       //should条件

      List<Pair<String, ?>> shouldTermConditions = should.getTermConditions();

      List<Pair<?, String>> shouldMatchConditions = should.getMatchConditions();

      Map<String, Pair<?, ?>> shouldRangeConditions = should.getRangeConditions();



  if (shouldTermConditions.size() > 0) {

    for (Pair<String, ?> shouldTermPair : shouldTermConditions) {

      if (shouldTermPair.getValue() instanceof Collection) {

        Collection<?> formatTermPair = (Collection<?>) shouldTermPair.getValue();

       TermsQueryBuilder termsShouldQueryBuilder = QueryBuilders.termsQuery(shouldTermPair.getKey(), formatTermPair);

       boolQueryBuilder.should(termsShouldQueryBuilder);

      } else {

       TermQueryBuilder termShouldQueryBuilder = QueryBuilders.termQuery(shouldTermPair.getKey(), shouldTermPair.getValue());

       boolQueryBuilder.should(termShouldQueryBuilder);

    }

  }

}

//匹配

  if (shouldMatchConditions.size() > 0) {

    for (Pair<?, String> shouldMatchPair : shouldMatchConditions) {

      if (shouldMatchPair.getKey() instanceof String[]) {

         String[] formatPairKey = (String[]) shouldMatchPair.getKey();

         MultiMatchQueryBuilder multiShouldMatchQueryBuilder = QueryBuilders

           .multiMatchQuery(shouldMatchPair.getValue(), formatPairKey)

           .analyzer("ik_max_word");

           boolQueryBuilder.should(multiShouldMatchQueryBuilder);

        } else if (shouldMatchPair.getKey() instanceof String) {

            String formatPairKey = (String) shouldMatchPair.getKey();

    MatchQueryBuilder shouldMatchQueryBuilder = QueryBuilders

.matchQuery(formatPairKey, shouldMatchPair.getValue())

.analyzer("ik_max_word");

boolQueryBuilder.should(shouldMatchQueryBuilder);

}

}

}

//范围

  if (shouldRangeConditions.size() > 0) {

     for (Map.Entry<String, Pair<?, ?>> shouldRangeEntry : shouldRangeConditions.entrySet()) {

          RangeQueryBuilder rangeShouldQueryBuilder = QueryBuilders.rangeQuery(shouldRangeEntry.getKey());

          rangeShouldQueryBuilder.to(shouldRangeEntry.getValue().getValue()).from(shouldRangeEntry.getValue().getKey());

          boolQueryBuilder.should(rangeShouldQueryBuilder);

        }

    }

}

//过滤条件

  if (termConditions.size() > 0) {

    for (Pair<String, ?> termPair : termConditions) {

      if (termPair.getValue() instanceof Collection) {

         Collection<?> formatTermPair = (Collection<?>) termPair.getValue();

         TermsQueryBuilder termsQueryBuilder =    QueryBuilders.termsQuery(termPair.getKey(), formatTermPair);

        boolQueryBuilder.filter(termsQueryBuilder);

 } else {

    TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(termPair.getKey(), termPair.getValue());

   boolQueryBuilder.filter(termQueryBuilder);

      }

  }

}

//匹配条件

  if (matchConditions.size() > 0) {

    for (Pair<?, String> matchPair : matchConditions) {

    if (matchPair.getKey() instanceof String[]) {

      String[] formatPairKey = (String[]) matchPair.getKey();

      MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(matchPair.getValue(), formatPairKey)

.analyzer("ik_max_word");

boolQueryBuilder.filter(multiMatchQueryBuilder);

} else if (matchPair.getKey() instanceof String) {

   String formatPairKey = (String) matchPair.getKey();

   MatchQueryBuilder matchQueryBuilder = QueryBuilders

  .matchQuery(formatPairKey, matchPair.getValue())

  .analyzer("ik_max_word");

   boolQueryBuilder.filter(matchQueryBuilder);

    }

  }

}

       //range条件

       if (rangeConditions.size() > 0) {

            for (Map.Entry<String, Pair<?, ?>> rangeEntry : rangeConditions.entrySet()) {

               RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(rangeEntry.getKey());

               rangeQueryBuilder.to(rangeEntry.getValue().getValue()).from(rangeEntry.getValue().getKey());

               boolQueryBuilder.filter(rangeQueryBuilder);

       }

    }

       return boolQueryBuilder;

}



/**

* 构造高亮器

*

* @param fieldNames

* @return

*/

private HighlightBuilder createHighlightBuilder(List<String> fieldNames) {

      HighlightBuilder highlightBuilder = new HighlightBuilder()

     .preTags("<span style='color:red'>")

     .postTags("</span>");

//设置高亮字段

     for (String fieldName : fieldNames) {

       highlightBuilder.field(fieldName);

     }
   return highlightBuilder;

  }

}

6.查询参数类

@Data

public class QueryParam {

/**

* 搜索内容

*/

  private String queryContent;

/**

* 性别

*/

  private String sex;

/**

* 姓名

*/

  private String name;

}

7.测试类

@Service

public class QueryServiceImpl extends EsSearchServiceImpl<EsQueryBean> {



@Override

  public List<EsQueryBean> query(PageParam pageParam, QueryParam queryParam) {

    String queryContent = queryParam.getQueryContent();

    String name = queryParam.getName();

    String sex = queryParam.getSex();



    BoTermQuery boTermQuery = BoTermQuery.create();

    BoTermQuery.Should should = BoTermQuery.Should.create(1);

    if (!StringUtils.isEmpty(queryContent)) {

      should.addMatchCondition(queryContent, "name", "content");

      boTermQuery.addShouldCondition(should);

    }

    if (!StringUtils.isEmpty(sex)) {

      boTermQuery.addTermCondition("sex", sex);

    }

    if (name != null) {

      boTermQuery.addMatchCondition("name", name);

    }

//List<EsQueryBean> esQueryBeans = this.queryList(pageParam, boTermQuery, EsQueryBean.class);

    List<String> highlightFields = new ArrayList<>();

    highlightFields.add("content");

    List<EsQueryBean> esQueryBeans = this.queryListHighlight(pageParam, boTermQuery, highlightFields,

    "query", EsQueryBean.class);

    return esQueryBeans;


  }



  @Override

  public BaseRecord queryDetail(EsComprehensiveQueryBean esComprehensiveQueryBean) {

    String sourceTableType = esComprehensiveQueryBean.getSourceTableName();

    EnumPeopleInfoTable tableEnum = EnumPeopleInfoTable.getEnumByTableName(sourceTableType);

    if (tableEnum == null) {

      log.info("没有此人员信息资源表:" + sourceTableType);

      throw new ExceptionBizSystem(EnumResponseCode.REQUEST_INTERFACE_PEOPLE_INFO_TABLE.code, EnumResponseCode.REQUEST_INTERFACE_PEOPLE_INFO_TABLE.message);

    }

    Map<String, Object> param = new HashMap<>();

    param.put("idCard", esComprehensiveQueryBean.getIdCard());

    Object obj = daoPeopleInfoQuery.findByParam(param, tableEnum.clazz);

    return (BaseRecord) obj;

  }

}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值