当前位置: 首页 > news >正文

网站开发平台是什么网站建设定制设计

网站开发平台是什么,网站建设定制设计,惠州网络营销,苏州网站建站如何实现 Es 全文检索、高亮文本略缩处理 前言技术选型JAVA 常用语法说明全文检索开发高亮开发Es Map 转对象使用核心代码 Trans 接口#xff08;支持父类属性的复杂映射#xff09;Trans 接口可优化的点高亮全局配置类如下真实项目落地效果为什么不用 numOfFragments、fragm… 如何实现 Es 全文检索、高亮文本略缩处理 前言技术选型JAVA 常用语法说明全文检索开发高亮开发Es Map 转对象使用核心代码 Trans 接口支持父类属性的复杂映射Trans 接口可优化的点高亮全局配置类如下真实项目落地效果为什么不用 numOfFragments、fragmentSize 参数控制略缩结语 前言 最近手上在做 Es 全文检索的需求类似于百度那种根据关键字检索出对应的文章然后高亮显示特此记录一下其实主要就是处理 Es 数据那块复杂涉及到高亮文本替换以及高亮字段截取还有要考虑到代码的复用性是否可以将转换代码抽离出来提供给不同结构的索引来使用。 技术选型 像市面上有的 Spring Data码云上面的 GVP 项目 EasyEs等其他封装框架。使用起来确实很方便但是考虑到由于开源项目的不稳定性且 Es 不同版本间语法差异比较大还有一方面是公司之前用的一直是 Es 6后续可能会涉及到 Es 的升级改造于是决定使用原生的 Api。也就是使用 RestHighLevelClient。 JAVA 常用语法说明 查时间范围内的数据 BoolQuery 里面嵌套一个 RangeQuery 即可在RangeQuery 里面指定时间范围。BoolQuery.must() 各位理解为 Mybatis 中的 eq 方法即可必须包含的意思。 RangeQueryBuilder rangeQuery QueryBuilders.rangeQuery(articleRequest.getSortType());if (StringUtils.isNotEmpty(articleRequest.getBeginTime())) {rangeQuery.gte(articleRequest.getBeginTime());}if (StringUtils.isNotEmpty(articleRequest.getEndTime())) {rangeQuery.lte(articleRequest.getEndTime());}boolQuery.must(rangeQuery);BoolQuery.should() 方法可以理解为 OR 可包含可不包含多字段全文检索时应用 shoud。 BoolQueryBuilder boolQuery QueryBuilders.boolQuery(); boolQuery.should(QueryBuilders.matchPhraseQuery(articleRequest.getKeys()[i], articleRequest.getKeyword()));termsQuery 字符精确匹配 QueryBuilders.termsQuery()字符短句匹配字符不会进行分词 QueryBuilders.matchPhraseQuery分词匹配 QueryBuilders.multiMatchQuery分词匹配加高亮对应 EQEs 的Sql我自己给他取的名字 GET /articlezzh/_doc/_search {from: 0,size: 20,query: {bool: {must: [{multi_match: {query: 你的购物节,fields: [title,author,body]}}]}},highlight: {pre_tags: [em stylecolor: red],post_tags: [/em],fields: {body:{},author:{}}} }全文检索开发 核心代码如下 BoolQueryBuilder boolQuery QueryBuilders.boolQuery();if (StringUtils.isNotEmpty(articleRequest.getKeyword())) {for (int i 0; i articleRequest.getKeys().length; i) {//根据短句匹配boolQuery.should(QueryBuilders.matchPhraseQuery(articleRequest.getKeys()[i], articleRequest.getKeyword()));}}高亮开发 里面可以指定高亮的字段以及高亮前缀尾缀API的调用直接 copy 就行。 SearchSourceBuilder searchSourceBuilder new SearchSourceBuilder().highlighter(new HighlightBuilder().requireFieldMatch(false).field(author).field(title).field(body).field(attachments.filename).preTags(EsConstant.HIGHT_PREFIX).postTags(EsConstant.HIGHT_END)//noMatchSize//返回全部内容方便后续的截取字符串操作.fragmentSize(800000).numOfFragments(0))//过滤数据最少满足一个 should 条件的数据才会被展示否则过滤.query(boolQuery.minimumShouldMatch(1)).from(articleRequest.getPage() - 1).size(articleRequest.getSize());Es Map 转对象使用 由于索引结构是已 ArticleResponse 格式存储的查询的时候也需将的得到 SourceAsMap 转换成 ArticleResponse 格式核心逻辑我都封装到 Trans 接口了。利用反射实现的当然也可以用其他技术实现例如 MapStruct 在编译期间就自动生成对应的 get、set 方法比反射效率高点毕竟反射是运行期间的属性映射 SearchHits hits restHighLevelClient.search(new SearchRequest().indices(indexname).source(searchSourceBuilder)).getHits();for (SearchHit hit : hits) {result.add(new ArticleResponse().trans(hit.getSourceAsMap(),hit.getHighlightFields(),Collections.singletonList(attachments.filename)));使用的话只需让 ArticleResponse 类实现 Trans 接口即可调用里面的 trans 方法。 核心代码 Trans 接口支持父类属性的复杂映射 主要逻辑就是挨个拿到本身、然后递归获取父类的所有字段名称、字段类型放到一个 MapnameTypeMap 中然后遍历 SourceAsMap 挨个进行字段类型匹配校验如果是 String 类型直接进行反射填充属性。 非 String 类型进行类型转换然后再进行属性填充。 以及高亮字段文本略缩的处理主要就是用了下 Jsoup 中去除 Html 标签的 Api,本来想着让前端自己去找插件看能不能处理下的无奈说处理不了想了个取巧的方法高亮标签我用特殊字符然后去除所有的 html 标签后我的特殊字符还存在之后将特殊字符再次替换回高亮 Html 标签这样就得到了只存在我自定义高亮 Html 标签的一段文本了同时高亮标签里面我塞了一个 id之后根据高亮标签中的 id 截取字符即可即可实现文本略缩的效果同事直呼秒啊哈哈哈哈 /*** map 转对象* authorzzh*/ public interface TransT {SimpleDateFormat simpleDateFormat new SimpleDateFormat(yyyy-MM-dd HH:mm:ss);Class getTargetClass();/*** 逻辑写的太多了可以搞几个抽象类抽分功能** param SourceAsMap 原始数据* param highlightFieldsSource 高亮数据* param highLightFields 高亮字段*/default Object trans(MapString, Object SourceAsMap, MapString, HighlightField highlightFieldsSource, ListString highLightFields) throws IntrospectionException, InstantiationException, IllegalAccessException {Object o getTargetClass().newInstance();Class tclass getTargetClass();HashMapString, Class nameTypeMap new HashMap();//找到父类的所有字段do {Arrays.stream(tclass.getDeclaredFields()).forEach(field - {field.setAccessible(true);//key字段名称value字段类型nameTypeMap.put(field.getName(), field.getType());});tclass tclass.getSuperclass();} while (!tclass.equals(Object.class));PropertyDescriptor[] propertyDescriptors Introspector.getBeanInfo(o.getClass()).getPropertyDescriptors();Arrays.stream(propertyDescriptors).forEach(propertyDescriptor - {if (!targetClass.equals(propertyDescriptor.getName()) !Objects.isNull(SourceAsMap.get(propertyDescriptor.getName()))) {try {Method writeMethod propertyDescriptor.getWriteMethod();if (null ! writeMethod) {if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {writeMethod.setAccessible(true);}Object sourceValue SourceAsMap.get(propertyDescriptor.getName());//父类以及自己所有字段类型Class aClass nameTypeMap.get(propertyDescriptor.getName());//String 类型以及高亮直接赋值if (sourceValue.getClass().equals(aClass)) {HighlightField highlightObject highlightFieldsSource.get(propertyDescriptor.getName());//如果高亮字段是 body为了避免高亮文本处于文章末尾搜索页显示不到的问题因此采用截取字符串将高亮字段偏移至前面if (EsConstant.HIGHT_FILED.equals(propertyDescriptor.getName()) null ! highlightObject) {String highlightString highlightObject.getFragments()[0].toString();//去除所有 html 标签并将自定义高亮前缀替换 span 标签这样就实现了只保留高亮标签的目的了highlightString Jsoup.parse(highlightString).body().text().replaceAll(EsConstant.HIGHT_PREFIX, EsConstant.HIGHT_PREFIX_HTML).replaceAll(EsConstant.HIGHT_END, EsConstant.HIGHT_END_HTML);//高亮字段前 50 个字到文章末尾highlightString highlightString.substring((highlightString.indexOf(EsConstant.HIGHT_HTML_ID) - EsConstant.HIGHT_SIZE) 0? 0 : (highlightString.indexOf(EsConstant.HIGHT_HTML_ID) - EsConstant.HIGHT_SIZE));writeMethod.invoke(o, highlightObject ! null ? highlightString : SourceAsMap.get(propertyDescriptor.getName()));} else if (EsConstant.HIGHT_FILED.equals(propertyDescriptor.getName()) null highlightObject) {//非高亮的 body 字段也去除下 Html 标签writeMethod.invoke(o, Jsoup.parse(String.valueOf(SourceAsMap.get(propertyDescriptor.getName()))).body().text());} else {//非 body 的其他高亮字段正常替换高亮文本writeMethod.invoke(o, highlightObject ! null ? highlightObject.getFragments()[0].toString().replaceAll(EsConstant.HIGHT_PREFIX, EsConstant.HIGHT_PREFIX_HTML).replaceAll(EsConstant.HIGHT_END, EsConstant.HIGHT_END_HTML) : SourceAsMap.get(propertyDescriptor.getName()));}}/*** 类型不一致强转这里可以搞个策略模式优化优化*/else {if (aClass.equals(Date.class)) {Date parse simpleDateFormat.parse(String.valueOf(SourceAsMap.get(propertyDescriptor.getName())));writeMethod.invoke(o, parse);}if (aClass.equals(Integer.class)) {writeMethod.invoke(o, Integer.valueOf(String.valueOf(SourceAsMap.get(propertyDescriptor.getName()))));}if (aClass.equals(Long.class)) {writeMethod.invoke(o, Long.valueOf(String.valueOf(SourceAsMap.get(propertyDescriptor.getName()))));}if (aClass.equals(List.class)) {//获取指定属性的 ListArrayListMapString, Object oraginSources (ArrayListMapString, Object) SourceAsMap.get(propertyDescriptor.getName());//复杂对象高亮字段映射if (null ! oraginSources 0 ! highlightFieldsSource.size()) {for (int i 0; i oraginSources.size(); i) {for (int j 0; j highLightFields.size(); j) {try {if (highlightFieldsSource.containsKey(highLightFields.get(j))) {oraginSources.get(i).put(highLightFields.get(j).split(\\.)[1],highlightFieldsSource.get(highLightFields.get(j)).getFragments()[j].toString().replaceAll(EsConstant.HIGHT_PREFIX, EsConstant.HIGHT_PREFIX_HTML).replaceAll(EsConstant.HIGHT_END, EsConstant.HIGHT_END_HTML));}} catch (Exception e) {e.printStackTrace();}}}}writeMethod.invoke(o, oraginSources);}if (aClass.equals(int.class)) {writeMethod.invoke(o, Integer.parseInt(String.valueOf(SourceAsMap.get(propertyDescriptor.getName()))));}}} else throw new RuntimeException(propertyDescriptor.getName() ~ writeMethod is null!!!!!);} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}}});return o;}} Trans 接口可优化的点 优化点一策略模式扩展多数据类型转换那部分的代码这里就不贴出来了。优化点二支持多高亮字段略缩处理也就是将这行代码改成 List 集合判断但是我感觉没必要一个字段略缩就够用了。 EsConstant.HIGHT_FILED.equals(propertyDescriptor.getName())配置文件也可以用策略模式或者利用 Spi 机制动态加载。针对项目要开源的情况下说的这块的内容可以看我以往写过的 Spi 文章。可以搞个文章内容里面涉及到关键字的地方就略缩一下举个例子查地瓜的时候返回的数据是这样的 …地瓜…地瓜而现在的效果是地瓜…希望别让我改我觉得我现在这样也够用了。代码逻辑再次解耦可以利用抽象类的性质按照功能细分职责,毕竟很多框架源码就是这么干的一堆的抽象类封装通用逻辑 高亮全局配置类如下 为了方便后期维护将用到的配置封装了一下大家可自行替换用 Nacos 配置中心也好还是用枚举类也好修改一下代码即可 public class EsConstant {//高亮前缀唯一 id可自行定义public static String HIGHT_PREFIX zzhSatat;//高亮尾缀唯一 id可自行定义public static String HIGHT_END zzhEnd;//高亮尾缀public static String HIGHT_END_HTML /span;//高亮标签 id可自行定义public static String HIGHT_HTML_ID zzh;//截取高亮字段前字符串长度public static int HIGHT_SIZE 50;//高亮前缀public static String HIGHT_PREFIX_HTML span stylecolor:red,id HIGHT_HTML_ID ;//略缩字段public static String HIGHT_FILED body; }真实项目落地效果 复杂对象高亮字段替换效果 为什么不用 numOfFragments、fragmentSize 参数控制略缩 数据库中的文章内容直接存的 Html 页面用这俩参数截取字符串的话截取到的文本会含残缺的 Html 标签效果直接 Pass当然对于纯文本类型的字段可以用这俩个参数进行控制不用写截取字符串的逻辑 结语 勿忘初心鼎力前行 如果您觉得文章对您有帮助的话 不妨点个免费的赞或者关注 这将成为我前进的最大动力 微信公众号刚刚起步后续创作更多精品内容提供给大家 有任何技术问题欢迎加我微信交流
http://www.w-s-a.com/news/410445/

相关文章:

  • 网站建设技术的发展最近的国际新闻大事
  • 德州有名的网站建设公司网站如何做引流
  • 建设一个收入支出持平的网站网络推广计划书格式
  • 什么是网站黑链全球新冠疫苗接种率
  • 网站开发 chrome gimp网站不备案做seo没用
  • 织梦校园招生网站源码沪佳哪个好
  • 建设企业网站可信度软件产品如何做网站推广
  • 网站建设企业号助手贵阳景观设计公司
  • 网站开发第三方建设银行个人网站显示不了
  • 无锡兼职做网站郑州网站建设搜索优化
  • iis禁止通过ip访问网站品牌策划案例ppt
  • 电子商务网站建设实习seo黑帽优化
  • 如何做好网站建设销售闸北集团网站建设
  • 重庆装饰公司北京官网seo推广
  • 深圳网站设计灵点网络品牌网站充值接口
  • 建设书局 网站国内国际时事图片
  • 成都 网站建设培训学校屏蔽wordpress自带编辑器
  • 公司网站制作工作室中天建设集团有限公司第五建设公司
  • 网站的网页设计毕业设计苏州宣传册设计广告公司
  • 商城网站优化方案注册公司制作网站
  • 政务服务网站建设整改报告wordpress的导航代码
  • 图片素材网站建设做教育网站用什么颜色
  • 快站淘客中转页wordpress商业插件
  • 可信网站网站认证免费软件下载网站免费软件下载网站
  • 小学生网站制作最新域名网站
  • 奖励网站代码设计制作ppt时
  • 茂名优化网站建设门户网站和部门网站的区别
  • 一尊网 又一个wordpress站点wordpress获取当前文章名称
  • 营销型网站多少钱新建网站的外链多久生效
  • 网站空间怎么选择tp5企业网站开发百度云