文章目录
- 1.DSL查询语法
-
- 1.1.DSL查询分类和基本语法
- 1.2.全文检索
- 1.3.精确查询
- 1.4.地理查询
- 1.5复合查询
- 2.查询结果处理
-
- 2.1.排序
- 2.2.分页
- 2.3.高亮
- 3.RestClient查询文档
- 4.RestClient处理结果
-
- 4.1分页与排序
- 4.2高亮
1.DSL查询语法 1.1.DSL查询分类和基本语法 常见的查询类型包括:
查询类型 | 描述 |
---|---|
查询所有 | 查询出所有数据 例如:match_all |
全文检索查询 | 利用分词器对用户输入内容分词,然后去倒排索引库中匹配。例如:match 、 multi_match |
精确查询 | 根据精确词条值查找数据,一般是查找keyword、数值、日期、boolean等类型字段。例如:ids、range、term |
地理查询 | 根据经纬度查询。例如:geo_distance、geo_bounding_box |
复合查询 | 复合查询可以将上述各种查询条件组合起来,合并查询条件。例如:bool、function_score |
GET /索引库名/_search
{
"query": {
"查询类型": {
"查询条件": "条件值"
}
}
}
【案例】
文章图片
1.2.全文检索 全文检索会对用户输入内容分词,常用于搜索框搜索
【match语法】
GET /索引库名/_search
{
"query": {
"match": {
"要搜索的字段": "搜索的值"
}
}
}
【multi_match语法】
GET /索引库名/_search
{
"query": {
"multi_match": {
"query": "搜索的值",
"fields": ["要搜索的字段1","要搜索的字段2","要搜索的字段3"]
}
}
}
【案例】
文章图片
参与查询的字段越多查询性能越差。建议使用match查询,将要查询的多个要查字段通过copy_to拷到一个字段中
1.3.精确查询 精确查询你一般是查找keyword、日期、boolean等字段类型,不会对搜索条件分词。
【term查询语法】
GET /索引库名/_search
{
"query": {
"term": {
"要搜索的字段": {
"value": "要搜索的值"
}
}
}
}
【range查询语法】范围查询:可以是数值也可以是日期
GET /hotel/_search
{
"query": {
"range": {
"要搜索的字段": {
"gte": 最小值,
"lte": 最大值
}
}
}
}
【案例】
文章图片
1.4.地理查询 根据经纬度查询
- geo_bounding_box:查询geo_point落在某个矩形范围内的所有文档
- geo_distance:查询到指定中心点小于某个举例值得所有文档
GET /hotel/_search
{
"query": {
"geo_bounding_box": {
"位置字段": {
"top_left": {
"lat": 维度位置,
"lon": 经度位置
},
"bottom_right": {
"lat": 经度位置,
"lon": 维度位置
}
}
}
}
}
【geo_distance查询语法】
GET /hotel/_search
{
"query": {
"geo_distance": {
"distance": "距离(例如15km)",
"位置字段": "经纬度"
}
}
}
【案例】
文章图片
1.5复合查询 复合查询可以将其他简单查询组合起来,实现更复杂的搜索逻辑
- function_score:算分函数查询,可以控制文档相关性算分,控制文档排名
- bool:布尔查询是一个或多个查询子句的组合
GET /索引库名/_search
{
"query": {
"function_score": {
"query": { //原始查询条件
"查询类型": {
"字段名": "值"
}
},
"functions": [
{
"filter": { //过滤条件,符合条件的文档才会被重新算分
"term": {
"字段名": "值"
}
},
"weight": 1 //算分函数
}
],
"boost_mode": "multiply" //加权模式
}
}
}
常见算分模式:
- weight:给一个常量值作为函数结果
- field_value_factor:用文档中的某个字段作为函数结果
- random_score:随机生成一个值作为函数的结果
- script_score:自定义计算公式,公式结果作为函数结果
文章图片
【bool语法】
GET /索引库名/_search
{
"query": {
"bool": {
"子查询一": [],
"子查询二": [],
"子查询三": [],
//...
}
}
}
子查询的组合方式有:
- must:必须匹配每个子查询,类似"与"
- should:选择性匹配子查询,类似"或"
- must_not:必须不匹配,不参与算分,类似"非"
- filter:必须匹配,不参与算分
文章图片
2.查询结果处理 2.1.排序 ElasticSearch默认按照相关度算分(_score)排序,ES允许指定自定义排序字段。可以排序的字段有:keyword类型、数值类型、地理坐标类型、日期类型等。
【语法】
GET /索引库名/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"参与排序的字段": {
"order": "desc"
}
}
]
}
【案例】
文章图片
【按照距离排序】
GET /hotel/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"_geo_distance": {
"location": {
"lat": 32.123,
"lon": 121.221
},
"order": "asc",
"unit": "km"
}
}
]
}
2.2.分页 ElasticSearch默认情况下只返回top10的数据,如果需要查询更多的数据就需要修改分页参数
【语法】
GET /hotel/_search
{
"query": {
"match_all": {}
},
"from": 45,//分页开始的位置,默认为0
"size": 15,//期望获得的文档总数,默认为10
"sort": [
{ "price": "asc"}
]
}
默认查询上限(from+size)是10000
2.3.高亮 【语法】
GET /hotel/_search
{
"query": {
"match": {
"name": "深圳"
}
},
"highlight": {
"fields": {
"name": { //指定要高亮的字段
"require_field_match": "false", //默认情况搜索字段要与高亮字段一致
"pre_tags": "",//标记高亮的前置标签
"post_tags": "" //标记高亮的后置标签
}
}
}
}
3.RestClient查询文档
@Test
void testMatchAll() throws IOException{
//1.准备request
SearchRequest searchRequest = new SearchRequest("hotel");
//2.准备DSL参数
//searchRequest.source().query(QueryBuilders.matchAllQuery());
//match_all查询
//searchRequest.source().query(QueryBuilders.matchQuery("name","北京"));
//match查询
//searchRequest.source().query(QueryBuilders.multiMatchQuery("南京","city","name"));
//multi_match查询
//searchRequest.source().query(QueryBuilders.termQuery("city","上海"));
//精确查询
//searchRequest.source().query(QueryBuilders.rangeQuery("price").gte(100).lte(200));
//范围查询
searchRequest.source().query(QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("city","上海"))
.filter(QueryBuilders.rangeQuery("price").gte(100).lte(200))
);
//组合查询//3.发送请求,得到响应结果
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
//4.解析响应结果
SearchHits searchHits = searchResponse.getHits();
//4.1获取查询的总条数
long total = searchHits.getTotalHits().value;
System.out.println(total);
//4.2查询结果的数组
SearchHit[] hits = searchHits.getHits();
for (SearchHit hit : hits) {
//4.3获取source
String json = hit.getSourceAsString();
//4.4反序列化成hotelDoc对象
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
System.out.println(hotelDoc);
}
}
4.RestClient处理结果 4.1分页与排序
@Test
void testSort() throws IOException{
int page = 2,size = 15;
SearchRequest searchRequest = new SearchRequest("hotel");
searchRequest.source().query(QueryBuilders.matchAllQuery());
//分页
searchRequest.source().from((page-1)*size).size(size);
//排序
searchRequest.source().sort("price", SortOrder.DESC);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
//....
}
4.2高亮
@Test
void testHeightLighter() throws IOException{
SearchRequest searchRequest = new SearchRequest("hotel");
searchRequest.source().query(QueryBuilders.termQuery("brand","喜来登"));
//高亮
searchRequest.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
//结果高亮处理
SearchHits searchHits = searchResponse.getHits();
SearchHit[] hits = searchHits.getHits();
for (SearchHit hit : hits) {
//4.3获取source
String json = hit.getSourceAsString();
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
Map 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);
}
}
推荐阅读
- java|关于ElasticSearch版本7.8.0进行排坑
- Elasticsearch掰开揉碎第3篇windows环境搭建
- Elasticsearch掰开揉碎第2篇linux环境搭建
- 低代码-业务流程引擎
- 前端基础和框架使用|Vue的异步渲染axios
- java|程序员加班实用贴 | 每日趣闻
- 人工智能|复旦博士生写了130行代码,用OCR和正则表达式快速搞定核酸报告统计!
- java|复旦博士写了130行代码,2分钟解决繁琐核酸报告核查
- Java|springboot疫情防控核酸检测管理系统