1、環境准備
(1)添加依賴
<dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> </dependency> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> </dependency>
(2)配置文件
application.yml
server: port: ${port:40100} spring: application: service-search elasticsearch: hostlist: - 127.0.0.1:9200 #多個節點中間用逗號分隔[addr1,addr2]
(3)創建配置類
package com.search.config; import java.util.ArrayList; import java.util.List; import org.apache.http.HttpHost; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import lombok.Getter; import lombok.Setter; @Configuration @ConfigurationProperties(prefix="elasticsearch") @Getter @Setter public class ElasticSearchConfig { private List<String> hostlist; @Bean public RestHighLevelClient restHighLevelClient(){ List<HttpHost> httpHostList = new ArrayList<>(hostlist.size()); //封裝es服務端地址 for(String host:hostlist){ HttpHost httpHost = new HttpHost(host.split(":")[0], Integer.parseInt(host.split(":")[1]), "http"); httpHostList.add(httpHost); } return new RestHighLevelClient(RestClient.builder(httpHostList.toArray(new HttpHost[0]))); } //把低級客戶端也注入,但是基本不用 @Bean public RestClient restClient(){ List<HttpHost> httpHostList = new ArrayList<>(hostlist.size()); //封裝es服務端地址 for(String host:hostlist){ HttpHost httpHost = new HttpHost(host.split(":")[0], Integer.parseInt(host.split(":")[1]), "http"); httpHostList.add(httpHost); } return RestClient.builder(httpHostList.toArray(new HttpHost[0])).build(); } }
2、索引管理測試
package com.search.test; import java.io.FileInputStream; import org.apache.commons.io.IOUtils; import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse; import org.elasticsearch.client.IndicesClient; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentType; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @SpringBootTest @RunWith(SpringRunner.class) public class TestIndex { @Autowired RestHighLevelClient client; @Autowired RestClient restClient; //創建索引庫 @Test public void testCreateIndex()throws Exception{ //創建索引請求對象、並設置索引名稱 CreateIndexRequest createIndexRequest = new CreateIndexRequest("course"); //設置參數 Settings settings = Settings.builder().put("number_of_shards", 1) .put("number_of_replicas",0) .build(); createIndexRequest.settings(settings); FileInputStream is = new FileInputStream(this.getClass().getResource("/").getPath()+"mapping.json"); String mappingJson = IOUtils.toString(is); System.err.println(mappingJson); //設置映射 createIndexRequest.mapping("doc",mappingJson,XContentType.JSON); //創建索引操作對象 IndicesClient indices = client.indices(); CreateIndexResponse createIndexResponse = indices.create(createIndexRequest); //獲得相應是否成功 boolean acknowledged = createIndexResponse.isAcknowledged(); System.out.println(acknowledged); } //刪除索引庫 @Test public void testDeleteIndex()throws Exception{ //穿建刪除索引庫請求對象 DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("course"); //刪除索引庫 DeleteIndexResponse deleteIndexResponse= client.indices().delete(deleteIndexRequest); //刪除結果 boolean acknowledged = deleteIndexResponse.isAcknowledged(); System.out.println(acknowledged); } }
mapping.json
{
"properties": {
"description": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
},
"name": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
},
"pic":{
"type":"text",
"index":false
},
"price": {
"type": "float"
},
"studymodel": {
"type": "keyword"
},
"timestamp": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
}
}
這里特別注意: 使用了比例因子浮點數 ,索引庫創建成功之后,在head客戶端,數據瀏覽的字段結構中沒有展示,但是實際數據中是存在的,已經成功了
3、文檔管理測試
package com.xuecheng.search.test; import java.io.FileInputStream; import java.io.InputStream; import java.util.HashMap; import java.util.Map; import org.apache.commons.io.IOUtils; import org.elasticsearch.action.delete.DeleteRequest; import org.elasticsearch.action.delete.DeleteResponse; import org.elasticsearch.action.get.GetRequest; import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.action.update.UpdateResponse; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.common.xcontent.XContentType; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @SpringBootTest @RunWith(SpringRunner.class) public class TestDocument { @Autowired private RestHighLevelClient client; //添加文檔 @Test public void testAddDoc() throws Exception{ //加載准備好了的json數據 InputStream is = new FileInputStream(this.getClass().getResource("/").getPath()+"document.json"); String docJsonStr = IOUtils.toString(is); System.err.println(docJsonStr); //獲取索引庫對象 IndexRequest indexRequest = new IndexRequest("course","doc"); //特別注意doc不要掉、否則報錯org.elasticsearch.action.ActionRequestValidationException: Validation Failed: 1: type is missing; indexRequest.source(docJsonStr, XContentType.JSON); //往索引庫添加文檔,這個動作也叫索引 IndexResponse indexResponse = client.index(indexRequest); //打印結果 System.out.println(indexResponse.getResult()); } /** * 查詢文檔(根據id查) * 結果 * { * "description":"Bootstrap是由Twitter推出的一個前台頁面開發框架,在行業之中使用較為廣泛。 * 此開發框架包 含了大量的CSS、JS程序代碼,可以幫助開發者(尤其是不擅長頁面開發的程序人員) * 輕松的實現一個不受瀏覽器限制的 精美界面效果。", * "name":"Bootstrap開發框架", * "studymodel":"201001", * "price":62.658 * } */ @Test public void testGetDoc()throws Exception{ GetRequest getRequest = new GetRequest("course", "doc", "TOFP1mcBf3IfcTiHcsXB"); GetResponse getResponse = client.get(getRequest); if(getResponse.isExists()){ String sourceAsString = getResponse.getSourceAsString(); System.out.println(sourceAsString); } } /** * 更新文檔 * 打印結果: OK * 注意這里采用的是局部更新:只修改map中設置的字段,沒有的不會更新。 * 更新文檔的實際順序是: 檢索文檔、標記刪除、創建新文檔、刪除原文檔 * 創建新文檔就會重構索引(分詞-重構倒排索引樹) * */ @Test public void testUpdateDoc()throws Exception{ UpdateRequest updateRequest = new UpdateRequest("course", "doc", "TOFP1mcBf3IfcTiHcsXB"); Map<String, String> map = new HashMap<String,String>(); map.put("name", "Bootstrap框架"); updateRequest.doc(map); UpdateResponse updateResponse = client.update(updateRequest); System.out.println(updateResponse.status()); } /** * 刪除文檔 * 打印結果:DELETED */ @Test public void testDelDoc() throws Exception{ DeleteRequest deleteRequest = new DeleteRequest("course", "doc", "TOFP1mcBf3IfcTiHcsXB"); DeleteResponse deleteResponse = client.delete(deleteRequest); System.out.println(deleteResponse.getResult()); } }
4、搜索管理測試
准備數據
初始化文檔:
{
"name": "Bootstrap開發",
"description": "Bootstrap是由Twitter推出的一個前台頁面開發框架,是一個非常流行的開發框架,此框架集成了多種頁面效果。此開發框架包含了大量的CSS、JS程序代碼,可以幫助開發者(尤其是不擅長頁面開發的程序人員)輕松的實現一個不受瀏覽器限制的精美界面效果。",
"studymodel": "201002",
"price":38.6,
"timestamp":"2018-04-25 19:11:35",
"pic":"group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg"
}
{
"name": "java編程基礎",
"description": "java語言是世界第一編程語言,在軟件開發領域使用人數最多。",
"studymodel": "201001",
"price":68.6,
"timestamp":"2018-03-25 19:11:35",
"pic":"group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg"
}
{
"name": "spring開發基礎",
"description": "spring 在java領域非常流行,java程序員都在用。",
"studymodel": "201001",
"price":88.6,
"timestamp":"2018-02-24 19:11:35",
"pic":"group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg"
}
測試
package com.xuecheng.search.test; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.MatchQueryBuilder; import org.elasticsearch.index.query.MultiMatchQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.TermQueryBuilder; import org.elasticsearch.index.query.TermsQueryBuilder; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder.Field; import org.elasticsearch.search.sort.FieldSortBuilder; import org.elasticsearch.search.sort.SortOrder; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @SpringBootTest @RunWith(SpringRunner.class) public class TeseSearch { @Autowired RestHighLevelClient client; @Autowired RestClient restClient; /** * 查詢type下所有文檔 * 打印結果: * {"studymodel":"201002","name":"Bootstrap開發"} {"studymodel":"201001","name":"java編程基礎"} {"studymodel":"201001","name":"spring開發基礎"} 對應http請求json { "query": { "match_all": {} }, "_source": ["name","studymodel"] } */ @Test public void testSearchAll()throws Exception{ //1、構造sourceBuild(source源) SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.fetchSource(new String[]{"name","studymodel"}, new String[]{}) .query(QueryBuilders.matchAllQuery()); //2、構造查詢請求對象 SearchRequest searchRequest = new SearchRequest("xc_course"); searchRequest.types("doc") .source(searchSourceBuilder); //3、client 執行查詢 SearchResponse searchResponse = client.search(searchRequest); //4、打印結果 SearchHits hits = searchResponse.getHits(); for(SearchHit hit:hits){ System.out.println(hit.getSourceAsString()); } } /** * 分頁查詢type下所有文檔 * * json 參數 * { * "from":0, * "size":1, * "query": { * "match_all": {} * }, * "_source": ["name","studymodel"] * } * * 打印結果 * {"studymodel":"201002","name":"Bootstrap開發"} {"studymodel":"201001","name":"java編程基礎"} */ @Test public void testSearchAllByPage()throws Exception{ //1、構造sourceBuild SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.fetchSource(new String[]{"name","studymodel"}, new String[]{}) .query(QueryBuilders.matchAllQuery()) .from(0).size(2);//分頁查詢,下表從0開始 //2、構造searchRequest請求對象 SearchRequest searchRequest = new SearchRequest("xc_course"); searchRequest.types("doc") .source(searchSourceBuilder); //3、client執行請求 SearchResponse searchResponse = client.search(searchRequest); //4、打印結果 SearchHits hits = searchResponse.getHits(); for(SearchHit hit:hits){ System.out.println(hit.getSourceAsString()); } } /** * term query: 精確查詢、在搜索是會精確匹配關鍵字、搜索關鍵字不分詞 * * json 參數 * { * * "query": { * "term": { * name: "spring" * } * }, * "_source": ["name","studymodel"] * } */ @Test public void testTermQuery()throws Exception{ //1、設置queryBuilder TermQueryBuilder termQueryBuild = QueryBuilders.termQuery("name","spring"); //2、設置sourceBuilder SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(termQueryBuild)//設置Term query查詢 .fetchSource(new String[]{"name","studymodel"}, new String[]{}); //3、構造searchRequest SearchRequest searchRequest = new SearchRequest("xc_course"); searchRequest.types("doc") .source(searchSourceBuilder); //4、client發出請求 SearchResponse searchResponse = client.search(searchRequest); //5、打印結果 SearchHits hits = searchResponse.getHits(); for(SearchHit hit:hits){ System.out.println(hit.getSourceAsString()); } } /** * 根據id精確查詢:根據提供的多個id去匹配 * * json 參數 * { * query{ "ids": { "type": "doc", "values": ["TeH_2WcBH5cUK","TuEB2mcBf3IfcTiHccWJ"] } * }, * "_source": ["name","studymodel"] * } */ @Test public void testIdsQuery()throws Exception{ //1、夠着queryBuild //構造idList,注意數組每個元素必須是一個完整的id能匹配的上,第一條沒有記錄匹配上,第二條中 String[] idList = new String[]{"TeH_2WcBH5cUK","TuEB2mcBf3IfcTiHccWJ"}; TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery("_id",idList);//特別注意用termsQuery,不要用termQuery //2、構造sourceBuilder SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(termsQueryBuilder) .fetchSource(new String[]{"name","studymodel"}, new String[]{});; //3、構造searchRequest SearchRequest searchRequest = new SearchRequest("xc_course"); searchRequest.types("doc") .source(searchSourceBuilder); //4、client執行 SearchResponse searchResponse = client.search(searchRequest); SearchHits hits = searchResponse.getHits(); //5、打印結果 for(SearchHit hit:hits){ System.out.println(hit.getSourceAsString()); } } /** * match Query就是全文檢索,收縮方式就是先將搜索字符串分詞、然后到索引分詞列表去匹配 * json 參數 * { * query{ * "match": { * "descrition":{ //還是需要指定字段的,description是字段名 * "query": "世界第一", * "operate": "or" //or表示分詞之后,只要有一個匹配即可,and表示分詞在文檔中都匹配才行 * } * }, * "_source": ["name","studymodel"] * } * } */ @Test public void testmatchQuery()throws Exception{ //queryBuild MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("description", "世界第一"); //searchSorcebuilder SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(matchQueryBuilder) .fetchSource(new String[]{"name","studymodel"}, new String[]{}); //searchRequest SearchRequest searchRequest = new SearchRequest("xc_course"); searchRequest.types("doc") .source(searchSourceBuilder); //client->search SearchResponse searchResponse = client.search(searchRequest); SearchHits hits = searchResponse.getHits(); //print end for(SearchHit hit:hits){ System.out.println(hit.getSourceAsString()); } } /** * minimum_should_match: * or只能表示只要匹配一個即可、minimum_should_match可以指定文檔匹配詞的占比,注意這個占比的基數是搜索字符串分詞的個數 * json 參數 * { * query{ * "match": { * "descrition":{ //還是需要指定字段的,description是字段名 * "query": "spring開發", * "minimun_should_match": "80%" * } * }, * "_source": ["name","studymodel"] * } * } */ @Test public void testMinimumShouldMatchQuery()throws Exception{ //queryBuild MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("description", "世界第一") .minimumShouldMatch("80%"); //searchSourceBuilder SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(matchQueryBuilder) .fetchSource(new String[]{"name","studymodel"}, new String[]{}); //searchRequest SearchRequest searchRequest = new SearchRequest("xc_course"); searchRequest.types("doc") .source(searchSourceBuilder); SearchResponse searchResponse = client.search(searchRequest); SearchHits hits = searchResponse.getHits(); for(SearchHit hit:hits){ System.out.println(hit.getSourceAsString()); } } /** * multi_match Query: * 用於一次匹配多個File進行全文檢索、前面match都是一個Field * 多個字段可以通過提升boost(權重),來提高得分,實現排序靠前 * * json 參數 * { * query{ * "multi_match": { * "query": "spring css", //搜索字符串 * "minimum_should_match": "50%", * "fields": ["name^10","description"] //設置匹配name 和 description字段,將boost的boost提10倍 * } * } * } */ @Test public void testMultiMatchQuery()throws Exception{ //queryBuilder MultiMatchQueryBuilder matchQueryBuilder = QueryBuilders.multiMatchQuery("Spring框架","name","description") .minimumShouldMatch("50%")//設置百分比 .field("name", 10);//提升boost //searchSourceBuild SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(matchQueryBuilder); //searchRequest SearchRequest searchRequest = new SearchRequest("xc_course"); searchRequest.types("doc") .source(searchSourceBuilder); //search SearchResponse searchResponse = client.search(searchRequest); SearchHits hits = searchResponse.getHits(); for(SearchHit hit:hits){ System.out.println(hit.getSourceAsString()); } } /** * 布爾查詢 * 對應lucene的Boolean查詢、實現將多個查詢條件結合起來 * 三個參數: * must:只有符合所有查詢的文檔才被查詢出來,相當於AND * should:至少符合其中一個,相當於OR * must_not:不能符合任意查詢條件,相當於NOT * * json 參數 * { * "_source": ["name","pic"], * "from": 0, * "size": 1, * query{ * bool:{ * must: [ * { * "multi_match": { * "query": "spring框架", * "minimum_should_match": "50%", * "fields": ["name^10","description"] * } * },{ * "term": { * "studymodel": "201001" * } * } * ] * } * } * } */ @Test public void testBooleanQuery()throws Exception{ //1、夠着QueryBuild //構造multiQureyBuilder MultiMatchQueryBuilder multiQueryBuilder = QueryBuilders.multiMatchQuery("Spring框架","name","description") .minimumShouldMatch("50%")//設置百分比 .field("name", 10); //構造termQueryBuilder TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("studymodel", "201001"); //構造booleanQueryBuilder BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery() .must(multiQueryBuilder) .must(termQueryBuilder); //2、構造查詢源 SearchSourceBuilder ssb = new SearchSourceBuilder(); ssb.fetchSource(new String[]{"name","pic"}, new String[]{}); ssb.query(boolQueryBuilder); //3、構造請求對象查詢 SearchRequest searchRequest = new SearchRequest("xc_course"); searchRequest.types("doc"); searchRequest.source(ssb); //4、client執行查詢 SearchResponse searchResponse = client.search(searchRequest); SearchHits hits = searchResponse.getHits(); for(SearchHit hit:hits){ System.out.println(hit.getSourceAsString()); } } /** * 過濾器: * 過濾器判斷的是文檔是否匹配,不去計算和判斷文檔的匹配度得分,所以過濾器性能比查詢高、方便緩存 * 推薦盡量使用過濾器、或則過濾器搭配查詢使用 * 過濾器使用的前提是bool查詢 * 過濾器可以單獨使用,但是不能提點multi Query, 因為過濾器每個Query都是單字段過濾 * * json 參數 * { * "_source": ["name","pic"], * "from": 0, * "size": 1, * query{ * bool:{ * must: [ * { * "multi_match": { * "query": "spring框架", * "minimum_should_match": "50%", * "fields": ["name^10","description"] * } * } * ], * fileter: [ * { * term: {"studymodel": "21001"} //針對字段進行過濾 * },{ * range: { //針對范圍進行過濾 * "price": {"gte":60,"lte":100} * } * } * ] * } * } * } */ @Test public void testFileter()throws Exception{ //1、構造QueryBuild //構造multiQureyBuilder MultiMatchQueryBuilder multiQueryBuilder = QueryBuilders.multiMatchQuery("Spring框架","name","description") .minimumShouldMatch("50%")//設置百分比 .field("name", 10); //構造booleanQueryBuilder BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery() .must(multiQueryBuilder); //過濾 boolQueryBuilder.filter(QueryBuilders.termQuery("studymodel", "201001")) .filter(QueryBuilders.rangeQuery("price").gte(60).lte(100)); //2、構造查詢源 SearchSourceBuilder ssb = new SearchSourceBuilder(); ssb.fetchSource(new String[]{"name","pic"}, new String[]{}); ssb.query(boolQueryBuilder); //3、構造請求對象查詢 SearchRequest searchRequest = new SearchRequest("xc_course"); searchRequest.types("doc"); searchRequest.source(ssb); //4、client執行查詢 SearchResponse searchResponse = client.search(searchRequest); SearchHits hits = searchResponse.getHits(); for(SearchHit hit:hits){ System.out.println(hit.getSourceAsString()); } } /** * 排序: * 可以設置排序字段對查詢結果進行排序 * keyword 、date 、float 等可以加 * 注意text 不能加 * * json 參數 * { * "_source": ["name","pic","description","price], * query{ * bool:{ * fileter: [ //過濾器也可以單獨使用,但是只能用於單個字段 * { * term: {"studymodel": "21001"} //針對字段進行過濾 * },{ * range: { //針對范圍進行過濾 * "price": {"gte":60,"lte":100} * } * } * ] * } * }, * "sort": [ * { * "studymodel": "desc" * },{ * "price": "asc" * } * ] * } */ @Test public void testSort()throws Exception{ //1、構造QueryBuild //構造booleanQueryBuilder BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); //過濾 boolQueryBuilder.filter(QueryBuilders.termQuery("studymodel", "201001")) .filter(QueryBuilders.rangeQuery("price").gte(60).lte(100)); //2、構造查詢源 SearchSourceBuilder ssb = new SearchSourceBuilder(); ssb.fetchSource(new String[]{"name","pic","studymodel","price"}, new String[]{}); ssb.query(boolQueryBuilder); ssb.sort(new FieldSortBuilder("studymodel").order(SortOrder.DESC)); ssb.sort(new FieldSortBuilder("price").order(SortOrder.ASC)); //3、構造請求對象查詢 SearchRequest searchRequest = new SearchRequest("xc_course"); searchRequest.types("doc"); searchRequest.source(ssb); //4、client執行查詢 SearchResponse searchResponse = client.search(searchRequest); SearchHits hits = searchResponse.getHits(); for(SearchHit hit:hits){ System.out.println(hit.getSourceAsString()); } } /** * 高亮顯示: * 將搜索結果中的一個或多個字突出顯示,以便向用戶展示匹配的關鍵字的位置 * * json 參數 */ @Test public void testHighlight()throws Exception{ //1、構造QueryBuild MultiMatchQueryBuilder multiQueryBuilder = QueryBuilders.multiMatchQuery("開發框架", "name","description") .field("name", 10) .minimumShouldMatch("50%"); //構造booleanQueryBuilder BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery() .must(multiQueryBuilder); //過濾 boolQueryBuilder.filter(QueryBuilders.termQuery("studymodel", "201001")) .filter(QueryBuilders.rangeQuery("price").gte(60).lte(100)); //2、設置高亮 //設置標簽 HighlightBuilder highlightBuilder = new HighlightBuilder(); highlightBuilder.preTags("<tag>")//設置簽綴 .postTags("</tag>");//設置后綴 //設置高亮字段 highlightBuilder.fields().add(new Field("name")); highlightBuilder.fields().add(new Field("description")); //3、構造查詢源 SearchSourceBuilder ssb = new SearchSourceBuilder(); ssb.fetchSource(new String[]{"name","pic","studymodel","price"}, new String[]{}) .query(boolQueryBuilder) .sort(new FieldSortBuilder("studymodel").order(SortOrder.DESC)) .sort(new FieldSortBuilder("price").order(SortOrder.ASC)) .highlighter(highlightBuilder); //4、構造請求對象查詢 SearchRequest searchRequest = new SearchRequest("xc_course"); searchRequest.types("doc") .source(ssb); //5、client執行查詢 SearchResponse searchResponse = client.search(searchRequest); //6、取出高亮字段 SearchHits hits = searchResponse.getHits(); for(SearchHit hit:hits){ System.out.println(hit.getHighlightFields()); } } }