DSL官方文档
function score query
官方文档
public class HotelSearchTest { private RestHighLevelClient client; @Test void testMatchAll() throws IOException { // 1. 准备Request SearchRequest request = new SearchRequest("hotel"); // 2. 准备DSL request.source().query(QueryBuilders.matchAllQuery()); // 3. 发送请求 SearchResponse response = client.search(request, RequestOptions.DEFAULT); // 4. 解析响应 SearchHits searchHits = response.getHits(); // 4.1 获取总条数 long total = searchHits.getTotalHits().value; System.out.println("共搜索到" + total + "条数据"); // 4.2 文档数组 SearchHit[] hits = searchHits.getHits(); // 4.3 遍历 for (SearchHit hit : hits) { // 获取文档source String json = hit.getSourceAsString(); // 反序列化 HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class); System.out.println("hotelDoc = " + hotelDoc); } System.out.println(response); } @BeforeEach void setUp(){ this.client = new RestHighLevelClient(RestClient.builder( HttpHost.create("http://192.168.10.88:9200") )); } @AfterEach void tearDown() throws IOException { this.client.close(); } }
// 全文检索查询 @Test void testMatch() throws IOException { // 1. 准备Request SearchRequest request = new SearchRequest("hotel"); // 2. 准备DSL request.source().query(QueryBuilders.matchQuery("all","皇冠")); // 3. 发送请求 SearchResponse response = client.search(request, RequestOptions.DEFAULT); handleResponse(response); System.out.println(response); } // bool查询 @Test void testBool() throws IOException { // 1. 准备Request SearchRequest request = new SearchRequest("hotel"); // 2. 准备DSL // 2.1 准备BooleanQuery BoolQueryBuilder boolQuery = QueryBuilders.boolQuery(); // 2.2 添加term boolQuery.must(QueryBuilders.termQuery("city","杭州")); // 2.3 添加range boolQuery.filter(QueryBuilders.rangeQuery("price").lte(250)); request.source().query(boolQuery); // 3. 发送请求 SearchResponse response = client.search(request, RequestOptions.DEFAULT); handleResponse(response); System.out.println(response); } // 抽取解析的代码 private static void handleResponse(SearchResponse response) { // 4. 解析响应 SearchHits searchHits = response.getHits(); // 4.1 获取总条数 long total = searchHits.getTotalHits().value; System.out.println("共搜索到" + total + "条数据"); // 4.2 文档数组 SearchHit[] hits = searchHits.getHits(); // 4.3 遍历 for (SearchHit hit : hits) { // 获取文档source String json = hit.getSourceAsString(); // 反序列化 HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class); System.out.println("hotelDoc = " + hotelDoc); } }
// 排序和分页 @Test void testPageAndSort() throws IOException { // 页码。每页大小 int page = 2, size = 5; // 1. 准备Request SearchRequest request = new SearchRequest("hotel"); // 2. 准备DSL // 2.1 query request.source().query(QueryBuilders.matchAllQuery()); // 2.2 配许sort request.source().sort("price", SortOrder.ASC); // 2.3 分页from, size request.source().from((page-1)*size).size(5); // 3. 发送请求 SearchResponse response = client.search(request, RequestOptions.DEFAULT); // 4. 解析响应 handleResponse(response); }
// 高亮 @Test void testHighlight() throws IOException { // 1. 准备Request SearchRequest request = new SearchRequest("hotel"); // 2. 准备DSL // 2.1 query request.source().query(QueryBuilders.matchQuery("all","如家")); // 2.2 高亮 request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false)); // 3. 发送请求 SearchResponse response = client.search(request, RequestOptions.DEFAULT); // 4. 解析响应 handleResponse(response); }
就是在前面抽取的解析代码中进一步添加关于高亮的解析部分,因为highlight和source是同级目录的,所以采用的方法类似。
// 抽取解析的代码 private static void handleResponse(SearchResponse response) { // 4. 解析响应 SearchHits searchHits = response.getHits(); // 4.1 获取总条数 long total = searchHits.getTotalHits().value; System.out.println("共搜索到" + total + "条数据"); // 4.2 文档数组 SearchHit[] hits = searchHits.getHits(); // 4.3 遍历 for (SearchHit hit : hits) { // 获取文档source String json = hit.getSourceAsString(); // 反序列化 HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class); // 获取高亮结果 MaphighlightFields = hit.getHighlightFields(); if(!CollectionUtils.isEmpty(highlightFields)){ // 根据字段名获取高亮结果 HighlightField highlightField = highlightFields.get("name"); if(highlightField != null){ // 获取高亮值 String name = highlightField.getFragments()[0].string(); // 覆盖非高亮结果 hotelDoc.setName(name); } } System.out.println("hotelDoc = " + hotelDoc); } }
@RestController @RequestMapping("/hotel") public class HotelController { @Autowired private IHotelService hotelService; @PostMapping("/list") public PageResult search(@RequestBody RequestParams params){ return hotelService.search(params); } }
@Service public class HotelService extends ServiceImplimplements IHotelService { @Autowired private RestHighLevelClient client; @Override public PageResult search(RequestParams params) { try {// 1. 准备Request SearchRequest request = new SearchRequest("hotel"); // 2. 准备DSL // 2.1 query String key = params.getKey(); if (key == null || "".equals(key)) { request.source().query(QueryBuilders.matchAllQuery()); } else { request.source().query(QueryBuilders.matchQuery("all", key)); } // 2.2 分页 int page = params.getPage(); int size = params.getSize(); request.source().from((page - 1) * size).size(size); // 3. 发送请求 SearchResponse response = client.search(request, RequestOptions.DEFAULT); // 4. 解析响应 return handleResponse(response); }catch (IOException e){ throw new RuntimeException(e); } } // 抽取解析的代码 private PageResult handleResponse(SearchResponse response) { // 4. 解析响应 SearchHits searchHits = response.getHits(); // 4.1 获取总条数 long total = searchHits.getTotalHits().value; // 4.2 文档数组 SearchHit[] hits = searchHits.getHits(); // 4.3 遍历 List hotels = new ArrayList<>(); for (SearchHit hit : hits) { // 获取文档source String json = hit.getSourceAsString(); // 反序列化 HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class); hotels.add(hotelDoc); } // 4.4 封装返回 return new PageResult(total,hotels); } }
@Override public PageResult search(RequestParams params) { try {// 1. 准备Request SearchRequest request = new SearchRequest("hotel"); // 2. 准备DSL // 2.1 query // 构建BooleanQuery buildBasicQuery(params, request); // 2.2 分页 int page = params.getPage(); int size = params.getSize(); request.source().from((page - 1) * size).size(size); // 3. 发送请求 SearchResponse response = client.search(request, RequestOptions.DEFAULT); // 4. 解析响应 return handleResponse(response); }catch (IOException e){ throw new RuntimeException(e); } } private static void buildBasicQuery(RequestParams params, SearchRequest request) { BoolQueryBuilder boolQuery = QueryBuilders.boolQuery(); // 关键字搜索 String key = params.getKey(); if (key == null || "".equals(key)) { boolQuery.must(QueryBuilders.matchAllQuery()); } else { boolQuery.must(QueryBuilders.matchQuery("all", key)); } // 条件过滤 // 城市 if(params.getCity() != null && !"".equals(params.getCity())){ boolQuery.filter(QueryBuilders.termQuery("city", params.getCity())); } // 品牌 if(params.getBrand() != null && !"".equals(params.getBrand())){ boolQuery.filter(QueryBuilders.termQuery("brand", params.getBrand())); } // 星级 if(params.getStarName() != null && !"".equals(params.getStarName())){ boolQuery.filter(QueryBuilders.termQuery("starName", params.getStarName())); } // 价格——范围过滤 if(params.getMinPrice() != null && params.getMaxPrice() != null){ boolQuery.filter(QueryBuilders.rangeQuery("price").gte(params.getMinPrice()).lte(params.getMaxPrice())); } request.source().query(boolQuery); }
// 2. 算分控制 FunctionScoreQueryBuilder functionScoreQuery = QueryBuilders.functionScoreQuery( // 原始查询,相关性算分的查询 boolQuery, // function score的数组 new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{ // 其中的一个function score元素 new FunctionScoreQueryBuilder.FilterFunctionBuilder( // 过滤条件 QueryBuilders.termQuery("isAD",true), // 算分函数 ScoreFunctionBuilders.weightFactorFunction(10) ) });