对于类似于这篇文章中的需求,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; }