Elasticsearch合并高亮字段

Posted lishaojun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
    

 

以上是关于Elasticsearch合并高亮字段的主要内容,如果未能解决你的问题,请参考以下文章

Elasticsearch--搜索

ElasticSearch多个字段分词查询高亮显示

Elasticsearch php 多字段高亮显示

Elasticsearch php 多字段高亮显示

Solr 高亮是不是还可以指示返回的片段在原始字段中的位置或偏移量?

Elasticsearch能检索出来,但不能正确高亮怎么办?