ES查询结果全局高亮
ES 查询结果全局高亮一、功能需求当我们用ES查询到结果后,想对命中关键词的实体的多个字段自动高亮,应该如何实现呢?需要实现这个功能,大概分为以下几个步骤:二、实现步骤构造查询方法,设置高亮(SearchHits方法)/*** 查询条件构造方法** @param indices 索引名称(需要从那个索引当中查询)* @param req查询条件* @param fields查询的文档(对应数据库的
·
一、功能需求
当我们用ES查询到结果后,想对命中关键词的实体的多个字段自动高亮,应该如何实现呢?
需要实现这个功能,大概分为以下几个步骤:
二、实现步骤
-
构造查询方法,设置高亮(
SearchHits方法
)/** * 查询条件构造方法 * * @param indices 索引名称(需要从那个索引当中查询) * @param req 查询条件 * @param fields 查询的文档(对应数据库的字段) * @return SearchHit */ public SearchHits queryBuilder(String indices, SearchREQ req, String[] fields) throws IOException { SearchSourceBuilder builder = new SearchSourceBuilder(); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); HighlightBuilder highlightBuilder = new HighlightBuilder(); //设置分页 if (req.getCurrent() > 0) { builder.from((int) req.getCurrent()); } if (req.getSize() > 0) { builder.size((int) req.getSize()); } //设置高亮 highlightBuilder.field("*"); //所有的字段都高亮 highlightBuilder.requireFieldMatch(false);//如果要多个字段高亮,这项要为false highlightBuilder.preTags("<font color='red'>").postTags("</font'>") .fragmentSize(800000)//下面这两项,如果你要高亮如文字内容等有很多字的字段,必须配置,不然会导致高亮不全,文章内容缺失等; 最大高亮分片数 .numOfFragments(0);//从第一个分片获取高亮片段 builder.highlighter(highlightBuilder); //构建查询条件 if (StringUtils.isNotEmpty(req.getUserId())) { boolQueryBuilder.must(QueryBuilders.matchQuery("userId", req.getUserId())); } //模糊查询 boolQueryBuilder.should(QueryBuilders.multiMatchQuery("*" + req.getText() + "*", fields)); //对查询结果进行排序 builder.query(boolQueryBuilder).sort("createDate", SortOrder.DESC); SearchRequest searchRequest = new SearchRequest(indices); searchRequest.source(builder); SearchResponse searchResponse = levelClientTests.search(searchRequest, RequestOptions.DEFAULT); return searchResponse.getHits(); }
-
调用查询方法,查询结果(
findObject
方法)public Result findObject(SearchREQ req) throws IOException, NoSuchFieldException { if (StringUtils.isEmpty(req.getText())) { return Result.error("查找内容不能为空"); } List<Object> resultList = null; Map<Object, Object> resultMap = new HashMap<>(); SearchHits hits; String indices = "mcb_article"; String[] fields = {"summary", "title", "mdContent"}; hits = queryBuilder(indices, req, fields); Article article = null; resultList = new ArrayList<>(); //遍历查询结果并接收 for (SearchHit searchHit : hits) { article = (Article) replaceAttr(searchHit, fields, indices); if (article != null) { resultList.add(article); } } }
-
使用工具替换实体的属性值(
replaceAttr
方法)/** * 替换高亮属性 * * @param searchHit 查询结果 * @param attrs 字段名 * @return * @throws JsonProcessingException * @throws NoSuchFieldException */ private Object replaceAttr(SearchHit searchHit, String[] attrs) throws JsonProcessingException, NoSuchFieldException { ObjectMapper objectMapper = new ObjectMapper(); EntityUtil util = new EntityUtil(); Object o = null; Article article = new Article(); for (String field : attrs) { Map<String, HighlightField> highlightFields = searchHit.getHighlightFields(); HighlightField hField = highlightFields.get(field); if (hField != null) { //替换高亮字段 Text[] fragments = hField.fragments(); StringBuilder text = new StringBuilder(); for (Text textGet : fragments) { text.append(textGet); } //对象的值只能读一次,否则会被覆盖 if (article.getId() == null) { article = objectMapper.readValue(searchHit. getSourceAsString(), article.getClass()); } //设置对象的属性值 util.setValue(article, Article.class,field, Article.class.getDeclaredField(field).getType(),text.toString()); o = article; continue; } } return o; }
-
设置对象的属性值()
/** * 实体工具 * @author MyLover * @date 2022.2.6 * @version 1.0.0 */ public class EntityUtil { /** * 设置对象对应的属性值 * @param obj 传入的对象 * @param clazz 传入对象的类 * @param filedName 需要设置的字段名 * @param typeClass 字段的类型 * @param value 需要设置的值 * 实例: 设置Article的id属性值为1 * Article article = new Article(); * String field = "id"; * setValue(article_es1,Article_ES.class,field, * Article.class.getDeclaredField(field).getType(),"1"); */ public void setValue(Object obj, Class<?> clazz, String filedName, Class<?> typeClass, Object value) { String methodName = "set" + filedName.substring(0, 1) .toUpperCase() + filedName.substring(1); try { Method method = clazz.getDeclaredMethod(methodName, typeClass); method.invoke(obj, getClassTypeValue(typeClass, value)); } catch (Exception ex) { ex.printStackTrace(); } } /** * 根据属性,获取对象的属性值, 例如: getGetMethod(Article,id) * @param ob 对象 * @param name 属性名 */ public Object getGetMethod(Object ob, String name) throws Exception { Method[] m = ob.getClass().getMethods(); for (Method method : m) { if (("get" + name).toLowerCase().equals(method.getName().toLowerCase())) { return method.invoke(ob); } } return null; } private Object getClassTypeValue(Class<?> typeClass, Object value) { if (typeClass == int.class || value instanceof Integer) { if (null == value) { return 0; } return value; } else if (typeClass == short.class) { if (null == value) { return 0; } return value; } else if (typeClass == byte.class) { if (null == value) { return 0; } return value; } else if (typeClass == double.class) { if (null == value) { return 0; } return value; } else if (typeClass == long.class) { if (null == value) { return 0; } return value; } else if (typeClass == String.class) { if (null == value) { return ""; } return value; } else if (typeClass == boolean.class) { if (null == value) { return true; } return value; } else if (typeClass == BigDecimal.class) { if (null == value) { return new BigDecimal(0); } return new BigDecimal(value + ""); } else { return typeClass.cast(value); } } }
更多推荐
已为社区贡献6条内容
所有评论(0)