完整代碼:https://github.com/qfjiaoyan/elasticsearch-examples
高亮介紹
許多應用都傾向於在每個搜索結果中 高亮 顯示搜索的關鍵詞,比如字體的加粗,改變字體的顏色等.以便讓用戶知道為何該文檔符合查詢條件。在 Elasticsearch 中檢索出高亮片段也很容易。
高亮顯示需要一個字段的實際內容。 如果該字段沒有被存儲(映射mapping沒有將存儲設置為 true),則加載實際的source,並從source中提取相關的字段。
以百度搜索“千鋒”為例,如下圖標紅的文字。
在 Elasticsearch 中檢索出高亮片段也很容易。
再次執行前面的查詢,並增加一個新的 highlight 參數:
<code>GET /megacorp/employee/_search
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
},
"highlight": {
"fields" : {
"about" : {}
}
}
}/<code>
當執行該查詢時,返回結果與之前一樣,與此同時結果中還多了一個叫做 highlight 的部分。這個部分包含了 about 屬性匹配的文本片段,並以 HTML 標籤 封裝:
<code>{
...
"hits": {
"total": 1,
"max_score": 0.23013961,
"hits": [
{
...
"_score": 0.23013961,
"_source": {
"first_name": "John",
"last_name": "Smith",
"age": 25,
"about": "I love to go rock climbing",
"interests": [ "sports", "music" ]
},
"highlight": {
"about": [
"I love to go rock climbing"
]
}
}
]
}
}/<code>
可以看到,除了從ES中得到標準信息以外,還有一個新命名的highlight的部分。這裡ES使用的這HTML標籤作為highlight部分的開始,使用/em>標識其結束。
高亮使用
highlight參數:
下面的參數可以改變返回的結果。即可以為單獨的字段設置不同的參數,也可以作為 highlight 的屬性統一定義。
number_of_fragments fragment 是指一段連續的文字。返回結果最多可以包含幾段不連續的文字。默認是5。
fragment_size 某字段的值,長度是1萬,但是我們一般不會在頁面展示這麼長,可能只是展示一部分。設置要顯示出來的fragment文本判斷的長度,默認是100
noMatchSize
搜索出來的這個文檔這個字段已經顯示出高亮的情況,可是其它字段並沒有任何顯示,設置這個屬性可以顯示出來。
pre_tags 標記 highlight 的開始標籤。例如上面的。
post_tags 標記 highlight 的結束標籤。例如上面的。
例如:以“中國蘋果”為關鍵詞搜索短信下發內容,並高亮顯示,HTML樣式為""./<font>
JAVA代碼示例:com.qianfeng.elasticsearch.query.impl.HightLightQueryImpl
<code>@Override
public void hightLightQuery(String indexName, String type,String field,String keyword) throws IOException {
SearchRequest searchRequest = new SearchRequest(indexName);
searchRequest.types(type);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.from(0);
searchSourceBuilder.size(5);
//條件
MatchQueryBuilder queryBuilder = new MatchQueryBuilder(field,keyword);
// 高亮設置
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.requireFieldMatch(false).field(field).
preTags("").postTags("/<font>");
searchSourceBuilder.highlighter(highlightBuilder);
searchSourceBuilder.query( queryBuilder);
searchRequest.source(searchSourceBuilder);
log.info("source string:" + searchRequest.source());
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
System.out.println("count:"+hits.totalHits);
SearchHit[] h = hits.getHits();
for (SearchHit hit : h) {
//得到高亮顯示的集合
Map<string> map = hit.getHighlightFields();
HighlightField highlightField = map.get(field);
// System.out.println("高"+map);
if (highlightField!=null){
System.out.println(highlightField.getName());
Text[] texts = highlightField.getFragments();
System.out.println("高亮顯示結果"+texts[0]);
}
System.out.println("普通字段結果"+hit.getSourceAsMap());
}
}/<string>/<code>
演示用例:com.qianfeng.elasticsearch.test.document.HightLightQueryTest
<code>@Test
public void testhightLightQuery() throws IOException {
hightLightQuery.hightLightQuery(indexName,type,"smsContent","中國蘋果");
}/<code>
把查詢結果另存為HTML文件,用瀏覽器打開結果顯示如下:
第二種情況:將fragmentSize設置為10
<code>@Override
public void hightLightQueryByFragment(String indexName, String type, int fragmentSize) throws IOException {
SearchRequest searchRequest = new SearchRequest(indexName);
searchRequest.types(type);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.from(0);
searchSourceBuilder.size(5);
//條件
MatchQueryBuilder queryBuilder = new MatchQueryBuilder("smsContent","企業");
// 高亮設置
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.requireFieldMatch(false).field("smsContent").
preTags("").postTags("");
highlightBuilder.fragmentSize(fragmentSize);
searchSourceBuilder.highlighter(highlightBuilder);
searchSourceBuilder.query( queryBuilder);
searchRequest.source(searchSourceBuilder);
log.info("source string:" + searchRequest.source());
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
System.out.println("count:"+hits.totalHits);
SearchHit[] h = hits.getHits();
for (SearchHit hit : h) {
//得到高亮顯示的集合
Map<string> map = hit.getHighlightFields();
HighlightField highlightField = map.get("smsContent");
if (highlightField!=null){
Text[] fragments3 = highlightField.getFragments();
for (Text text : fragments3) {
System.out.println("result:"+text);
}
}
}
}/<string>/<code>
演示用例:com.qianfeng.elasticsearch.test.document.HightLightQueryTest
<code>@Test
public void testHightLightQueryByFragment() throws IOException, InterruptedException {
//fragment-size 指定高亮字段最大字符長度
SmsSendLog smsSendLog5 = new SmsSendLog();
smsSendLog5.setMobile("13600000088");
smsSendLog5.setCorpName("中國移動");
smsSendLog5.setCreateDate(new Date());
smsSendLog5.setSendDate(new Date());
smsSendLog5.setIpAddr("10.126.2.8");
smsSendLog5.setLongCode("10690000998");
smsSendLog5.setReplyTotal(60);
smsSendLog5.setProvince("湖北省");
smsSendLog5.setOperatorId(1);
smsSendLog5.setSmsContent("新京報快訊 7月16日,國家發改委網站發佈《關於印發的通知》(下稱《通知》),該《通知》表示,要完善國有企業退出機制。推動國有“殭屍企業”破產退出。對符合破產等退出條件的國有企業,各相關方不得以任何方式阻礙其退出,防止形成“殭屍企業”。不得通過違規提供政府補貼、貸款等方式維繫“殭屍企業”生存,有效解決國有“殭屍企業”不願退出的問題。國有企業退出時,金融機構等債權人不得要求政府承擔超出出資額之外的債務清償責任。《通知》還稱,完善特殊類型國有企業退出制度。針對全民所有制企業、廠辦集體企業存在的出資人已註銷、工商登記出資人與實際控制人不符、賬務賬冊資料嚴重缺失等問題,明確市場退出相關規定,加快推動符合條件企業退出市場,必要時通過強制清算等方式實行強制退出。\\n" +
"\\n" +
"《通知》表示,要建立市場主體退出預警機制。強化企業信息披露義務。提高企業財務和經營信息透明度,強化信息披露義務主體對信息披露真實性、準確性、完整性的責任要求。公眾公司應依法向公眾披露財務和經營信息。非公眾公司應及時向股東和債權人披露財務和經營信息。鼓勵非公眾公司特別是大型企業集團、國有企業參照公眾公司要求公開相關信息。強化企業在陷入財務困境時及時向股東、債權人等利益相關方的信息披露義務。");
docService.add(indexName,type, JSON.toJSONString(smsSendLog5),"220");
Thread.sleep(2000);
hightLightQuery.hightLightQueryByFragment(indexName,type,20);
}/<code>
搜索結果:
第三種情況:把numOfFragments設置為1
<code>@Override
public void hightLightQueryByNumOfFragments(String indexName, String type, int fragmentSize,int numOfFragments) throws IOException {
SearchRequest searchRequest = new SearchRequest(indexName);
searchRequest.types(type);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.from(0);
searchSourceBuilder.size(5);
//條件
MatchQueryBuilder queryBuilder = new MatchQueryBuilder("smsContent","企業");
// 高亮設置
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.requireFieldMatch(false).field("smsContent").
preTags("").postTags("");
highlightBuilder.fragmentSize(fragmentSize);
highlightBuilder.numOfFragments(numOfFragments);
searchSourceBuilder.highlighter(highlightBuilder);
searchSourceBuilder.query( queryBuilder);
searchRequest.source(searchSourceBuilder);
log.info("source string:" + searchRequest.source());
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
System.out.println("count:"+hits.totalHits);
SearchHit[] h = hits.getHits();
for (SearchHit hit : h) {
//得到高亮顯示的集合
Map<string> map = hit.getHighlightFields();
HighlightField highlightField = map.get("smsContent");
if (highlightField!=null){
Text[] fragments3 = highlightField.getFragments();
for (Text text : fragments3) {
System.out.println("高亮顯示結果:"+text);
}
}
}
}/<string>/<code>
演示用例:com.qianfeng.elasticsearch.test.document.HightLightQueryTest
<code>@Test
public void testHightLightQueryByNumOfFragments() throws IOException {
hightLightQuery.hightLightQueryByNumOfFragments(indexName,type,20,2);
}/<code>
搜索結果:
第四種情況:將noMatchSize設置進來
<code>@Override
public void hightLightNoMatchSize(String indexName, String type, int fragmentSize,int numOfFragments,int noMatchSize) throws IOException {
SearchRequest searchRequest = new SearchRequest(indexName);
searchRequest.types(type);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.from(0);
searchSourceBuilder.size(5);
//條件
BoolQueryBuilder builder = QueryBuilders.boolQuery();
MatchQueryBuilder querySmsContentBuilder = new MatchQueryBuilder("smsContent","企業");
MatchQueryBuilder queryCorpNameBuilder = new MatchQueryBuilder("corpName","企業");
builder.should(querySmsContentBuilder);
builder.should(queryCorpNameBuilder);
// 高亮設置
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.requireFieldMatch(false).field("smsContent").field("corpName").
preTags("").postTags("");
highlightBuilder.fragmentSize(fragmentSize);
highlightBuilder.numOfFragments(numOfFragments);
highlightBuilder.noMatchSize(noMatchSize);
searchSourceBuilder.highlighter(highlightBuilder);
searchSourceBuilder.query(builder);
searchRequest.source(searchSourceBuilder);
log.info("source string:" + searchRequest.source());
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
System.out.println("count:"+hits.totalHits);
SearchHit[] h = hits.getHits();
for (SearchHit hit : h) {
//得到高亮顯示的集合
Map<string> map = hit.getHighlightFields();
HighlightField highlightField1 = map.get("corpName");
if(highlightField1!=null) {
Text[] fragments1 = highlightField1.getFragments();
for (Text text : fragments1) {
System.out.println("1:" + text);
}
}
HighlightField highlightField2 = map.get("smsContent");
if (highlightField2!=null){
Text[] fragments3 = highlightField2.getFragments();
for (Text text : fragments3) {
System.out.println("2:"+text);
}
}
}
}/<string>/<code>
演示用例:com.qianfeng.elasticsearch.test.document.HightLightQueryTest
<code>@Test
public void testHightLightNoMatchSize() throws IOException {
hightLightQuery.hightLightNoMatchSize(indexName,type,30,2,150);
}/<code>
搜索結果
完整代碼:https://github.com/qfjiaoyan/elasticsearch-examples
閱讀更多 Java教研組 的文章