zoukankan      html  css  js  c++  java
  • Elasticsearch合并高亮字段

    对于类似于这篇文章中的需求,Elasticsearch实现英文区分大小写搜索,创建了两个采用不同分词器内容相同的字段,实施搜索时,正常如果只有一个搜索条件,直接搜索某一个字段即可,但是如果有多两个搜索条件,比如:有两个搜索框,一个是区分大小写搜索,另外一个时正常的模糊搜索,这时在显示高亮的时候就会有问题,因为高亮的内容在两个字段里,而且高亮的部分不一样,这时就需要合并高亮,取高亮部分的并集。

    举例:

    高亮1:        String str1 = "have <a>a good job</a>,and <a>to get a happy</a> day.";
    高亮2:        String str2 = "have a <a>good</a> job,and to <a>get a happy day</a>.";
    合并结果: have <a>a good job</a>,and <a>to get a happy day</a>.

    合并过程其实就是处理字符串的过程,可能有很多种方式,这里提供一种简单高效的思路:

    1、获取每个高亮每个字符是否高亮的标记,true or false ,得到两个标记的集合;

    2、合并这两个集合中标记,当标记为true时就为合并的高亮。

        public static void main(String[] args) {
    
            String str = "have a good job,and to get a happy day.";
            String str1 = "have <a>a good job</a>,and <a>to get a happy</a> day.";
            String str2 = "have a <a>good</a> job,and to <a>get a happy day</a>.";
    
            ArrayList<Boolean> marks1 = getMarks(str1);
            ArrayList<Boolean> marks2 = getMarks(str2);
    
            // 合并标记
            long s = System.currentTimeMillis();
            StringBuilder result = new StringBuilder();
            boolean change = false;
            boolean before = false;
            for (int i = 0; i < marks1.size(); i++) {
                boolean current = marks1.get(i) || marks2.get(i);
                // 有变化
                change = before == !current;
                // 有变化且变为true
                if (change && current) {
                    result.append("<a>");
                    // 有变化且变为false
                } else if (change && !current) {
                    result.append("</a>");
                }
                result.append(str.charAt(i));
                before = current;
            }
                System.out.println(result);
    
            long e = System.currentTimeMillis();
            System.out.println(e - s);
        }
    
        // 标记字符串
        private static ArrayList<Boolean> getMarks(String str) {
            String pattern = "<a>(.*?)</a>";
            Pattern p = Pattern.compile(pattern);
            Matcher matcher = p.matcher(str);
    
            ArrayList<Boolean> marks = new ArrayList<>();
            int end = 0;
            while (matcher.find()) {
                String inside = matcher.group(1);
                for (int i = end; i < matcher.start(); i++) {
                    marks.add(false);
                }
                for (int i = 0; i < inside.length(); i++) {
                    marks.add(true);
                }
                end = matcher.end();
            }
            for (int i = end; i < str.length(); i++) {
                marks.add(false);
            }
            return marks;
        }
  • 相关阅读:
    http与https的区别以及https的加密原理
    android 网络之 httppost
    android 定时器与Canvas结合使用
    逛超市遇到问题了还是好心人多
    获取最新前十篇文章
    做菜 蒸鸡蛋
    使用ASP.NET 2.0 Profile存储用户信息_1[翻译] Level 200
    ajax 笔记不用刷新实现数据的分页显示 2 (上)
    在人力资源树当中,上级对下级员工信息查看修改操作。
    今年入冬于来的第一场雪
  • 原文地址:https://www.cnblogs.com/lishaojun/p/11027497.html
Copyright © 2011-2022 走看看