六、DSL查询
1. DSL查询分类和基本语法
-
1.DSL Query的分类
-
-
- 查询DSL的基本语法
-
GET /索引库名/_search
-
{ "query": { "查询类型": { "FIELD": "TEXT"}}}
-
举例:
-
GET /hotel/_search { "query": { "match_all": {} } }
2. 全文检索查询
-
全文检索查询,会对用户输入内容分词,常用于搜索框搜索
-
match和multi_match的区别是什么
-
match:根据一个字段查询
-
multi_match:根据多个字段查询,参与查询字段越多,查询性能越差
-
举例:
-
# match查询 GET /hotel/_search { "query": { "match": { "all": "海滩如家" } } } # multi_match查询 GET /hotel/_search { "query": { "multi_match": { "query": "外滩如家", "fields": ["brand","name","business"] } } } -
总结:尽量多用match,如果需要多字段查询,尽量使用copy_to去将多个查询字段合并
3. 精确查询
-
精确查询一般是查找keyword、数值、日期、boolean等类型字段。所以不会对搜索条件分词。
-
# term查询:根据词条精确匹配,一般搜索keyword类型、数值类型、布尔类型、日期类型字段 GET /hotel/_search { "query": { "term": { "city": { "value": "上海" } } } } # range查询:根据数值范围查询,可以是数值、日期的范围 GET /hotel/_search { "query": { "range": { "price": { "gte": 100, # gt 大于 gte大于等于 "lte": 300 # lt 小于 lte小于等于 } } } }
4. 地理查询
-
根据经纬度查询
-
第一种:geo_bounding_box:查询geo_point值落在某个矩形范围的所有文档
-
# geo_bounding_box查询 GET /indexName/_search { "query": { "geo_bounding_box": { "FIEID": { "top_left": { "lat": 31.1, "lon": 121.5 }, "bottom_right": { "lat": 30.9, "lon": 121.7 } } } } } -
第二种:geo_distance:查询到指定中心点小于某个距离值的所有文档
-
# distance查询 GET /hotel/_search { "query": { "geo_distance": { "distance": "15km", "location": "31.21,121.5" } } }
5. 相关性算分
6. Funcation Score Query
- 可以修改文档的相关性算分,根据新得到的算分排序
-
举例
-
# function score查询 GET /hotel/_search { "query": { "function_score": { "query": { "match": { "all": "外滩" } }, "functions": [ { "filter": { "term": { "brand": "如家" } }, "weight": 10 } ], "boost_mode": "sum" } } }
7. Boolean Query
-
举例:搜索名字包含”如家“,价格不高于400,在坐标31.21,121.5周围10km范围内的酒店
-
GET /hotel/_search { "query": { "bool": { "must": [ { "match": { "name": "如家" } } ], "must_not": [ { "range": { "price": { "gt": 400 } } } ], "filter": [ { "geo_distance": { "distance": "10km", "location": { "lat": 31.21, "lon": 121.5 } } } ] } } } # 或者 GET /hotel/_search { "query": { "bool": { "must": [ { "match": { "name": "如家" } } ], "filter": [ { "range": { "price": { "gt": 0, "lt": 400 } } }, { "geo_distance": { "distance": "10km", "location": { "lat": 31.21, "lon": 121.5 } } } ] } } }
七、搜索结果处理
1. 排序
-
对酒店数据按照用户评价降序排序,评价相同的按照价格升序排序
-
# sort排序 GET /hotel/_search { "query": { "match_all": {} }, "sort": [ { "score":"desc" }, { "price": "asc" } ] } -
找到121.612282,31.034661周围的酒店,举例升序排序
-
GET /hotel/_search { "query": { "match_all": {} }, "sort": [ { "_geo_distance": { "location": { "lat": 31.034661, "lon": 121.612282 }, "order": "asc", "unit": "km" } } ] }
2. 分页
-
举例
-
# 分页查询 GET /hotel/_search { "query": { "match_all": {} }, "sort": [ { "price": "asc" } ], "from": 0, "size": 2 }
3. 高亮
-
案例代码
-
# 高亮查询,默认情况下,ES搜索字段必须与高亮字段一致,我们可以 # 修改属性require_fied_match为false(这样就不必搜索字段和高亮字段一致),默认为true GET hotel/_search { "query": { "match": { "all": "如家" } }, "highlight": { "fields": { "name": { "require_field_match": "false" } } } }4. 总结
八、RestClient查询文档
1. 快速入门
-
实例代码
-
@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); } }
2. 通过RestClient进行各种查询
-
要构建查询条件,只要记住一个类:QueryBuilders
-
示例代码
-
@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); }@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(550)); request.source().query(boolQuery); // 3. 发送请求 SearchResponse response = client.search(request, RequestOptions.DEFAULT); handleResponse(response); } private 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); } }
3. 排序、分页
@Test
void testPageAndSort() throws IOException {
int page = 1, size = 5;
// 1. 准备request
SearchRequest request = new SearchRequest("hotel");
// 2. 准备DSL
// 2.1 query
request.source().query(QueryBuilders.matchAllQuery());
// 2.2 from、size
request.source().from((page - 1) * size).size(5);
// 2.3 sort
request.source().sort("price", SortOrder.ASC);
// 3. 发送请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
handleResponse(response);
}
4. 高亮显示
@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);
handleResponse(response);
}
private 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);
// 获取高亮结果
Map<String, HighlightField> highlightFields = 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);
}
}
5. 组合查询function score
- 本篇文章结合黑马课程来做的笔记