记录一下SpringBoot集成Elastic Search

7 篇文章 0 订阅
2 篇文章 0 订阅

在pom.xml引入依赖

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

定义一个通用的实体类

所有业务中使用到的实体类都可以继承这个通用的实体类。

@Data
public class CommonEsModel implements Serializable {
   @Id
   private Long id;
   @Field(type = FieldType.Text, analyzer = "ik_smart")
   private String code;
   @Field(type = FieldType.Text, analyzer = "ik_smart")
   private String fondsCode; // 全宗编号
   @Field(type = FieldType.Text, analyzer = "ik_smart")
   private String title;
   @Field(type = FieldType.Text, analyzer = "ik_smart")
   private Long typeId; // 分类id
   @Field(type = FieldType.Text, analyzer = "ik_smart")
   private Integer type;
   @Field(type = FieldType.Text, analyzer = "ik_smart")
   private String fileCode; // 文件编号
   @Field(type = FieldType.Text, analyzer = "ik_smart")
   private String unitCode; // 档号
   @Field(type = FieldType.Text, analyzer = "ik_smart")
   private String custodyCom; // 保管部门
   @Field(type = FieldType.Text, analyzer = "ik_smart")
   private String manager; // 责任人
   @Field(type = FieldType.Text, analyzer = "ik_smart")
   private String secret; // 密级
   @Field(type = FieldType.Text, analyzer = "ik_smart")
   private Integer year; // 年度
   @Field(type = FieldType.Text)
   private String createBy;
   @Field(type = FieldType.Date, pattern = "yyyy-MM-dd HH:mm:ss")
   private Date createTime;
   @Field(type = FieldType.Long)
   private Long deptId;
   @Field(type = FieldType.Long)
   private Long tenantId;
   /**
    * ES中存储的用于模糊搜索、高亮显示的字段
    */
   @Field(type = FieldType.Text, analyzer = "ik_max_word")
   private String desc;
   /**
    * 文件内容
    */
   @Field(type = FieldType.Text, analyzer = "ik_max_word")
   private String content;
}

定义一个通用的Dao

public interface CommonEsDao<O extends CommonEsModel> extends ElasticsearchRepository<O, Long> {
}

定义一个通用的Service

@Service
public class CommonEsService<O extends CommonEsModel, D extends CommonEsDao<O>> {

   private final D esDao;
   private final ElasticsearchRestTemplate elasticsearchRestTemplate;

   public CommonEsService(ElasticsearchRestTemplate elasticsearchRestTemplate, D esDao) {
      this.elasticsearchRestTemplate = elasticsearchRestTemplate;
      this.esDao = esDao;
   }

   /**
    * 分页查询(带关键字和高亮)
    *
    * @param clz            映射的实体类
    * @param keywords       搜索的关键字
    * @param highLightField 高亮的字段
    * @param orderBy        排序字段
    */
   public Page<O> page(Integer current, Integer size, Class<O> clz, String keywords, String[] highLightField, String orderBy) {
      BoolQueryBuilder defaultQueryBuilder = QueryBuilders.boolQuery();

      if (StringUtils.isNotEmpty(keywords)) {
         // 全文模糊搜索
         for (String s : highLightField) {
            defaultQueryBuilder.should(QueryBuilders.matchQuery(s, keywords));
         }
      }
      // 分页条件
      PageRequest pageRequest = PageRequest.of(current - 1, size);
      // 高亮条件
      HighlightBuilder highlightBuilder = getHighlightBuilder(highLightField);
      highlightBuilder.requireFieldMatch(false);
      // 排序条件
      FieldSortBuilder sortBuilder = SortBuilders.fieldSort(orderBy).order(SortOrder.DESC);
      //组装条件
      NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
            .withQuery(defaultQueryBuilder)
            .withHighlightBuilder(highlightBuilder)
            .withPageable(pageRequest)
            .withSorts(sortBuilder)
            .build();
      // 查询
      SearchHits<O> searchHits = elasticsearchRestTemplate.search(searchQuery, clz);
      // 高亮字段映射
      List<O> list = Lists.newArrayList();
      for (SearchHit<O> searchHit : searchHits) {
         O content = searchHit.getContent();
         Map<String, List<String>> highlightFields = searchHit.getHighlightFields();
         for (String highlightField : highlightFields.keySet()) {
            // 设置高亮,这里仅为示例,实际项目中建议使用自定义的高亮字段通过反射或获取及设值
            if (StringUtils.equals(highlightField, "desc")) {
               content.setDesc(highlightFields.get(highlightField).get(0));
            }
         }
         list.add(content);
      }
      // 组装分页对象
      return new PageImpl<>(list, pageRequest, searchHits.getTotalHits());
   }

   /**
    * 高级查询(带关键字和高亮)
    *
    * @param clz            映射的实体类
    * @param termQuery      精准匹配的键值对,键为字段名称,值为要匹配的内容
    * @param keywordsQuery  关键字匹配的键值对
    * @param highLightField 高亮的字段
    * @param orderBy        排序字段
    */
   public Page<O> page(Integer current, Integer size, Class<O> clz, Map<String, Object> termQuery, Map<String, Object> keywordsQuery,
                  String[] highLightField, String orderBy, Set<Long> tenantIds) {
      if (CollectionUtils.isEmpty(tenantIds)) {
         return Page.empty();
      }
      BoolQueryBuilder defaultQueryBuilder = QueryBuilders.boolQuery();

      // 精准匹配条件组装
      if (CollectionUtils.isNotEmpty(termQuery)) {
         for (String s : termQuery.keySet()) {
            defaultQueryBuilder.should(QueryBuilders.termQuery(s, termQuery.get(s)));
         }
      }
      defaultQueryBuilder.should(QueryBuilders.termsQuery("tenantId", tenantIds));
      // 模糊搜索条件组装
      if (CollectionUtils.isNotEmpty(keywordsQuery)) {
         for (String s : keywordsQuery.keySet()) {
            defaultQueryBuilder.should(QueryBuilders.matchQuery(s, keywordsQuery.get(s)));
         }
      }
      // 分页条件
      PageRequest pageRequest = PageRequest.of(current - 1, size);
      // 高亮条件
      HighlightBuilder highlightBuilder = getHighlightBuilder(highLightField);
      highlightBuilder.requireFieldMatch(false);
      // 排序条件
      FieldSortBuilder sortBuilder = SortBuilders.fieldSort(orderBy).order(SortOrder.DESC);
      //组装条件
      NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
            .withQuery(defaultQueryBuilder)
            .withHighlightBuilder(highlightBuilder)
            .withPageable(pageRequest)
            .withSorts(sortBuilder)
            .build();
      // 查询
      SearchHits<O> searchHits = elasticsearchRestTemplate.search(searchQuery, clz);
      // 高亮字段映射
      List<O> list = Lists.newArrayList();
      for (SearchHit<O> searchHit : searchHits) {
         O content = searchHit.getContent();
         Map<String, List<String>> highlightFields = searchHit.getHighlightFields();
         for (String highlightField : highlightFields.keySet()) {
            for (String s : highLightField) {
               // 设置高亮,这里仅为示例,实际项目中建议使用自定义的高亮字段通过反射或获取及设值
               if (StringUtils.equals(highlightField, "desc")) {
                  content.setDesc(highlightFields.get(highlightField).get(0));
               }
            }
         }
         list.add(content);
      }
      // 组装分页对象
      return new PageImpl<>(list, pageRequest, searchHits.getTotalHits());
   }

   /**
    * 设置高亮字段
    */
   private HighlightBuilder getHighlightBuilder(String... fields) {
      // 高亮条件
      HighlightBuilder highlightBuilder = new HighlightBuilder(); //生成高亮查询器
      for (String field : fields) {
         highlightBuilder.field(field);//高亮查询字段
      }
      highlightBuilder.requireFieldMatch(false);     //如果要多个字段高亮,这项要为false
      highlightBuilder.preTags("<span style=\"color:red\">");   //高亮设置
      highlightBuilder.postTags("</span>");
      //下面这两项,如果你要高亮如文字内容等有很多字的字段,必须配置,不然会导致高亮不全,文章内容缺失等
      highlightBuilder.fragmentSize(800000); //最大高亮分片数
      highlightBuilder.numOfFragments(0); //从第一个分片获取高亮片段
      return highlightBuilder;
   }

   /**
    * 通过id同ES中查询数据
    */
   public O getById(Long id) {
      Optional<O> byId = esDao.findById(id);
      boolean present = byId.isPresent();
      if (present) {
         return byId.get();
      }
      return null;
   }

   /**
    * 向ES保存数据
    */
   public O save(O o) {
      return esDao.save(o);
   }

   /**
    * 保存/修改数据,如果id存在,则修改,否则保存
    */
   public O updateOrSave(O o) {
      return esDao.save(o);
   }

   /**
    * 通过id从ES中删除数据
    */
   public void delete(Long id) {
      esDao.deleteById(id);
   }

业务代码中调用

业务实体类

@Data
@Document(indexName = "yj_es_archives")
public class EsArchives extends CommonEsModel {
}

Service层引用

private final ElasticsearchRestTemplate elasticsearchRestTemplate;
private final EsArchivesDao dao;
private CommonEsService<EsArchives, EsArchivesDao> esService() {
	return new CommonEsService<>(elasticsearchRestTemplate, dao);
}

private org.springframework.data.domain.Page<EsArchives> pageFromEs(Integer current, Integer size, ArchivesPriorSearch search) {
	List<ArchivesFonds> fonds = fondsService.listCurrentUserFonds();
	if (CollectionUtils.isEmpty(fonds)) {
		return org.springframework.data.domain.Page.empty();
	}
	Set<Long> tenantIds = fonds.stream().map(ArchivesFonds::getId).collect(Collectors.toSet());
    // 组装精准匹配的条件
	Map<String, Object> termQuery = new HashMap<>();
	if (StringUtils.isNotEmpty(search.getCustodyCom())) {
		termQuery.put("custodyCom", search.getCustodyCom());
	}
	if (Objects.nonNull(search.getTypeId())) {
		termQuery.put("typeId", search.getTypeId());
	}
	if (Objects.nonNull(search.getYear())) {
		termQuery.put("year", search.getYear());
	}
    // 组装关键字匹配的条件
	Map<String, Object> keywordsQuery = new HashMap<>();
	if (StringUtils.isNotEmpty(search.getKeywords())) {
		keywordsQuery.put("desc", search.getKeywords());
		keywordsQuery.put("content", search.getKeywords());
	}
	if (StringUtils.isNotEmpty(search.getCode())) {
		keywordsQuery.put("code", search.getCode());
	}
	if (StringUtils.isNotEmpty(search.getManager())) {
		keywordsQuery.put("manager", search.getManager());
	}
	if (StringUtils.isNotEmpty(search.getTitle())) {
		keywordsQuery.put("title", search.getTitle());
	}
	if (StringUtils.isNotEmpty(search.getSecret())) {
		keywordsQuery.put("secret", search.getTitle());
	}
	if (StringUtils.isNotEmpty(search.getUnitCode())) {
		keywordsQuery.put("unitCode", search.getUnitCode());
	}
	if (StringUtils.isNotEmpty(search.getFondsCode())) {
		keywordsQuery.put("fondsCode", search.getFondsCode());
	}
	if (StringUtils.isNotEmpty(search.getFileCode())) {
		keywordsQuery.put("fileCode", search.getFileCode());
	}
	String[] highLightField = new String[]{"code", "title", "desc", "content"};
	return esService().page(current, size, EsArchives.class, termQuery, keywordsQuery, highLightField, "createTime", tenantIds);
}

这样就可以啦。

效果如下

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值