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;
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM