济南网站建设是什么意思,如何用ae做模板下载网站,wordpress 网络图片,wordpress qq空间主题文章目录 前言#xff1a;RestClient 查询文档的 RestAPI一、全文检索查询1.1 match_all 查询1.2 match 查询1.3 multi_match 查询 二、精确查询2.1 term 查询2.2 range 查询 三、复合查询#xff1a;Boolean 查询与 function score 查询的综合案例四、对查询结果的处理4.1 将… 文章目录 前言RestClient 查询文档的 RestAPI一、全文检索查询1.1 match_all 查询1.2 match 查询1.3 multi_match 查询 二、精确查询2.1 term 查询2.2 range 查询 三、复合查询Boolean 查询与 function score 查询的综合案例四、对查询结果的处理4.1 将查询结果按照自己的距离远近排序4.2 根据前端请求参数进行分页操作4.3 对搜索关键字进行高亮处理 前言RestClient 查询文档的 RestAPI
在 Elasticsearch 中通过 RestAPI 进行 DSL 查询语句的构建通常是通过 HighLevelRestClient 中的 resource() 方法来实现的。该方法包含了查询、排序、分页、高亮等所有功能为构建复杂的查询提供了便捷的接口。 RestAPI 中构建查询条件的核心部分是由一个名为 QueryBuilders 的工具类提供的。该工具类包含了各种查询方法如下图所示 查询的基本步骤如下
创建 SearchRequest 对象。准备 Request.source()也就是 DSL。使用 QueryBuilders 构建查询条件。将查询条件传入 Request.source().query() 方法。发送请求得到结果。解析结果可以参考 JSON 结果从外到内逐层解析。
这种方式使得构建复杂的查询变得简单而灵活。在接下来的实例中我们将深入学习如何使用 HighLevelRestClient 中的 resource() 方法构建各种查询并充分利用 QueryBuilders 工具类来满足不同的搜索需求。
一、全文检索查询
1.1 match_all 查询
match_all 查询的单元测试代码
Test
void testMatchAll() throws IOException {// 1. 准备RequestSearchRequest request new SearchRequest(hotel);// 2. 组织 DSL 请求request.source().query(QueryBuilders.matchAllQuery());// 3. 发送请求SearchResponse response client.search(request, RequestOptions.DEFAULT);// 4. 解析结果ListHotelDoc hotelDocs handleResponse(response);System.out.println(hotelDocs);
}这个测试代码演示了如何使用 match_all 查询来获取指定索引这里是 “hotel”下的所有文档。具体步骤如下
创建 SearchRequest 对象指定索引为 “hotel”。使用 QueryBuilders.matchAllQuery() 构建查询条件。将查询条件添加到请求的 DSL 中。发送请求得到查询结果。解析查询结果将文档转换为 HotelDoc 对象。
1.2 match 查询
Test
void testMatch() throws IOException {// 1. 准备RequestSearchRequest request new SearchRequest(hotel);// 2. 组织 DSL 请求request.source().query(QueryBuilders.matchQuery(all, 如家));// 3. 发送请求SearchResponse response client.search(request, RequestOptions.DEFAULT);// 4. 解析结果ListHotelDoc hotelDocs handleResponse(response);System.out.println(hotelDocs);
}这个测试代码演示了如何使用 match 查询来搜索包含特定关键词这里是 “如家”的文档。具体步骤如下
创建 SearchRequest 对象指定索引为 “hotel”。使用 QueryBuilders.matchQuery(all, 如家) 构建查询条件表示在 “all” 字段中搜索包含 “如家” 的文档。将查询条件添加到请求的 DSL 中。发送请求得到查询结果。解析查询结果将文档转换为 HotelDoc 对象。
1.3 multi_match 查询
Test
void testMultiMatch() throws IOException {// 1. 准备RequestSearchRequest request new SearchRequest(hotel);// 2. 组织 DSL 请求request.source().query(QueryBuilders.multiMatchQuery(如家, name, business));// 3. 发送请求SearchResponse response client.search(request, RequestOptions.DEFAULT);// 4. 解析结果ListHotelDoc hotelDocs handleResponse(response);System.out.println(hotelDocs);
}这个测试代码演示了如何使用 multi_match 查询来在多个字段这里是 “name” 和 “business”中搜索包含特定关键词这里是 “如家”的文档。具体步骤如下
创建 SearchRequest 对象指定索引为 “hotel”。使用 QueryBuilders.multiMatchQuery(如家, name, business) 构建查询条件表示在 “name” 和 “business” 字段中搜索包含 “如家” 的文档。将查询条件添加到请求的 DSL 中。发送请求得到查询结果。解析查询结果将文档转换为 HotelDoc 对象。
可以看到这些测试代码的结构类似只是在构建查询条件时使用了不同的 QueryBuilders 方法用于满足不同的查询需求。
二、精确查询
精确查询常见的有 term 查询和 range 查询同样使用 QueryBuilders 指定具体的查询方式。
2.1 term 查询
Test
void testTerm() throws IOException {// 1. 准备RequestSearchRequest request new SearchRequest(hotel);// 2. 组织 DSL 请求request.source().query(QueryBuilders.termQuery(city, 上海));// 3. 发送请求SearchResponse response client.search(request, RequestOptions.DEFAULT);// 4. 解析结果ListHotelDoc hotelDocs handleResponse(response);System.out.println(hotelDocs);
}这个测试代码演示了如何使用 term 查询来搜索指定字段这里是 “city”中包含特定关键词这里是 “上海”的文档。具体步骤如下
创建 SearchRequest 对象指定索引为 “hotel”。使用 QueryBuilders.termQuery(city, 上海) 构建查询条件表示在 “city” 字段中搜索包含 “上海” 的文档。将查询条件添加到请求的 DSL 中。发送请求得到查询结果。解析查询结果将文档转换为 HotelDoc 对象。
2.2 range 查询
Test
void testRange() throws IOException {// 1. 准备RequestSearchRequest request new SearchRequest(hotel);// 2. 组织 DSL 请求request.source().query(QueryBuilders.rangeQuery(price).gte(150).lte(200));// 3. 发送请求SearchResponse response client.search(request, RequestOptions.DEFAULT);// 4. 解析结果ListHotelDoc hotelDocs handleResponse(response);System.out.println(hotelDocs);
}这个测试代码演示了如何使用 range 查询来搜索指定字段这里是 “price”中在给定范围内的文档。具体步骤如下
创建 SearchRequest 对象指定索引为 “hotel”。使用 QueryBuilders.rangeQuery(price).gte(150).lte(200) 构建查询条件表示在 “price” 字段中搜索价格在 150 到 200 之间的文档。将查询条件添加到请求的 DSL 中。发送请求得到查询结果。解析查询结果将文档转换为 HotelDoc 对象。
这些测试代码演示了如何使用精确查询来满足特定的搜索需求。在实际应用中可以根据具体的业务场景和数据结构选择不同的查询方式。
三、复合查询Boolean 查询与 function score 查询的综合案例
例如现在通过一个酒店预订网址的查询功能不但可以在搜索框输入关键字进行查询还可以勾选指定的筛选条件比如城市、星级、品牌和价格范围 另外再所有的酒店数据中还存在一部分属于广告ES 文档中新增一个布尔类型的 isAD 字段表示要求查询结果中的广告需要顶置显示因此整个查询分为两部分即 boolean 查询和 function score 查询。
boolean 查询实现对搜索关键字的查询以及过滤城市、星级、品牌和价格等条件function score 查询实现对广告文档的相关性增加操作。
具体的查询代码如下
private static void buildBasicQuery(RequestParams params, SearchRequest request) {// 1. 原始查询 QueryBoolQueryBuilder boolQuery QueryBuilders.boolQuery();// 关键字搜索 mustString key params.getKey();if (key null || key.isEmpty()) {boolQuery.must(QueryBuilders.matchAllQuery());} else {boolQuery.must(QueryBuilders.matchQuery(all, key));}// 城市条件if (params.getCity() ! null !params.getCity().isEmpty()) {boolQuery.filter(QueryBuilders.termQuery(city, params.getCity()));}// 品牌条件if (params.getBrand() ! null !params.getBrand().isEmpty()) {boolQuery.filter(QueryBuilders.termQuery(brand, params.getBrand()));}// 星级条件if (params.getStarName() ! null !params.getStarName().isEmpty()) {boolQuery.filter(QueryBuilders.termQuery(starName, params.getStarName()));}// 价格范围if (params.getMaxPrice() ! null params.getMinPrice() ! null) {boolQuery.filter(QueryBuilders.rangeQuery(price).lte(params.getMaxPrice()).gte(params.getMinPrice()));}// 2. 算分查询FunctionScoreQueryBuilder functionScoreQuery QueryBuilders.functionScoreQuery(// 原始查询相关信算法的查询boolQuery,// function score 数组new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{// 其中一个具体的 function scorenew FunctionScoreQueryBuilder.FilterFunctionBuilder(// 过滤条件QueryBuilders.termQuery(isAD, true),// 算分函数ScoreFunctionBuilders.weightFactorFunction(10))});request.source().query(functionScoreQuery);
}对上述代码的详细说明
RequestParams 是一个封装了前端请求参数的对象里面包含了 ES 文档中的各个字段在这个方法中首先构建了一个 boolQuery 作为原始查询条件包含了关键字搜索、城市、品牌、星级和价格范围等多个条件接着构建了一个 functionScoreQuery将原始查询作为参数传入同时定义了一个 FilterFunctionBuilder用于处理广告部分的查询对广告文档的分数进行加权使其在查询结果中更靠前显示最后将 functionScoreQuery 设置为请求的查询条件。
这个综合的查询案例涵盖了多个条件的组合查询以及对特定文档的加权分数处理。在实际应用中可以根据业务需求扩展和修改这个查询方法。
四、对查询结果的处理
4.1 将查询结果按照自己的距离远近排序
在前端查询酒店数据的时候一般都会定位获取到自己当前的位置然后传递给后端。
RequestParams 作为前端参数的封装对象包含了这个位置信息可通过get 方法进行获取然后可以通过 SortBuilders 中的 geoDistanceSort 方法计算距离并进行排序操作即可获取酒店与自己的实际距离。
String location params.getLocation();
if (location ! null !location.isEmpty()) {request.source().sort(SortBuilders.geoDistanceSort(location, new GeoPoint(location)).order(SortOrder.ASC).unit(DistanceUnit.KILOMETERS));
}4.2 根据前端请求参数进行分页操作
分页需要的页码以及页面大小一般都由前端传递参数给后端然后后端获取这两个参数进行分页操作。
RequestParams 作为前端参数的封装对象包含了这两个参数可通过get 方法进行获取然后再根据分页偏移量的计算公式offset (page - 1) * size 即可获取偏移量然后通过 source 的 from 和 size 方法即可实现分页查询。
例如
int page params.getPage();int size params.getSize();request.source().from((page - 1) * size).size(size);4.3 对搜索关键字进行高亮处理
要对搜索关键字进行高亮处理同样非常简单只需要使用 resouce 中的 highlighter 方法指定要进行高亮的字段即可。
实现的示例代码如下
Test
void testHighlight() throws IOException {// 1. 准备RequestSearchRequest request new SearchRequest(hotel);// 2. 组织 DSL 请求// 2.1 queryrequest.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. 解析结果ListHotelDoc hotelDocs handleResponse(response);System.out.println(hotelDocs);
}说明
注意requireFieldMatch方法的作用是高亮的字段是否需要和搜索的字段匹配。例如使用字段 all 查询匹配 brand 字段此时 brand 字段使用了 copy_to 到 all 字段因此要高亮的字段并不匹配如果不设置 requireFieldMatch 为 false 则会高亮失败。
对结果的解析 实现高亮的原理是对搜索关键字加上了 em /em 标签通过在 Kibana 中使用高亮处理的 DSL 语句可以发现 其实高亮的处理并没有作用到查询出的原始文档中而是在每个 hits 里面新增了一个 highlight 字段里面包含了高亮的关键字因此还需要对 handleResponse 函数进行改造使得能够处理高亮的查询结果
例如在handleResponse 函数的 result.add(hotelDoc) 这句代码之前新增了以下代码用于处理高亮的情况即使用高亮处理了的关键字替换查询结果中对应的关键字
// 获取高亮结果
MapString, HighlightField highlightFields hit.getHighlightFields();
if(highlightFields ! null !highlightFields.isEmpty()) {// 获取高亮名称HighlightField highlightField highlightFields.get(name);// 获取高亮的值String name highlightField.getFragments()[0].toString();hotelDoc.setName(name);
}当运行这段测试代码即可发现成功对 name 字段的 “如家” 添加了 em /em 标签