当前位置: 首页> 文旅> 旅游 > 乌鲁木齐市电话号码黄页_深圳形象设计公司_腾讯新闻最新消息_精品成品网站源码

乌鲁木齐市电话号码黄页_深圳形象设计公司_腾讯新闻最新消息_精品成品网站源码

时间:2025/7/12 23:24:28来源:https://blog.csdn.net/2301_80687933/article/details/144178937 浏览次数:0次
乌鲁木齐市电话号码黄页_深圳形象设计公司_腾讯新闻最新消息_精品成品网站源码

一、DSL查询文档

Elasticsearch提供了基于JSON的DSL(Domain Specific  Language)来定义查询。常见的查询类型包括:

1. DSL 查询分类概述

查询所有:查询出所有数据,一般测试用。例如:match_all

全文检索(full text)查询:利用分词器对用户输入内容分词,然后去倒排索引库中匹配。例如:

match_query、multi_match_query

精确查询:根据精确词条值查找数据,一般是查找keyword、数值、日期、boolean等类型字段。例如:ids、range、term

地理(geo)查询:根据经纬度查询。例如:geo_distance、geo_bounding_box

复合(compound)查询:复合查询可以将上述各种查询条件组合起来,合并查询条件。例如:bool、function_score

基本语法

GET /索引库名/_search

{

  "query"{

    "查询类型"{

      "查询条件""条件值"

    }

  }

}

例如:查询所有 

// 查询所有
GET /indexName/_search
{"query": {"match_all": {}}
}

2. 全文检索查询

全文检索查询,会对用户输入内容分词,常用于搜索框搜索:

1. match查询:全文检索查询的一种,会对用户输入内容分词,然后去倒排索引库检索,根据一个字段查询,语法:

GET   /索引名/_search

{

  "query"{

    "match"{

      "FIELD""TEXT"

    }

  }

}

如:条件查询 酒店吗为”7天酒店“ 的数据

GET /hotel/_search
{"query": {"match": {"all": "7天酒店"}}
}

2. multi_match:与match查询类似,只不过允许同时查询多个字段,根据多个字段查询,参与查询字段越多,查询性能越差。语法:

GET   /索引名/_search

{

  "query": {

    "multi_match": {

      "query""TEXT",

      "fields": ["FIELD1"" FIELD12"]

    }

  }

}

如:满足"brand", "name", "business" 任意字cha

GET /hotel/_search
{"query": {"multi_match": {"query": "7天酒店","fields": ["brand", "name", "business"]}}
}

3. 精准查询

精确查询一般是查找keyword、数值、日期、boolean等类型字段。所以不会对搜索条件分词。常见的有:

  • term:根据词条精确值查询
  • range:根据值的范围查询

 term 查询:根据词条精确匹配,一般搜索keyword类型、数值类型、布尔类型、日期类型字段

// term查询

GET  /索引名/_search

{

  "query"{

    "term"{

      "FIELD"{

        "value""VALUE"

      }

    }

  }

}

搜索城市为”上海“ 的酒店

GET /hotel/_search
{"query": {"term": {"city": {"value": "上海"}}}
}

range 查询:根据数值范围查询,可以是数值、日期的范围

// range查询

GET /索引名/_search

{

  "query"{

    "range"{

      "FIELD": {

        "gte"10,

        "lte"20

      }

    }

  }

}

搜索价格区间大于等于100且小于等于300的酒店

GET /hotel/_search
{"query": {"range": {"price": {"gte": "100",    #gte大于等于, gt大于"lte": "300"    # lte 小于等于, lt 小于}}}
}

4. 地理坐标查询

根据经纬度查询。常见的使用场景包括:搜索附近的人,附近的酒店等。

1.  geo_bounding_box:查询左上角和右下角相交形成的矩形范围内的所有文档

// geo_bounding_box查询

GET /索引名/_search

{

  "query": {

    "geo_bounding_box": {

      "FIELD": {

        "top_left": {

          "lat"31.1,

          "lon"121.5

        },

        "bottom_right": {

          "lat"30.9,

          "lon"121.7

        }

      }

    }

  }

}

2.  geo_distance:查询指定中心点及半径所形成的圆的所有文档

// geo_distance 查询

GET  /索引名/_search

{

  "query": {

    "geo_distance": {

      "distance""15km",

      "FIELD""31.21,121.5"

    }

  }

}

5. 复合查询

复合查询可以将其它简单查询组合起来,实现更复杂的搜索逻辑,例如:

fuction score:算分函数查询,可以控制文档相关性算分,控制文档排名。例如百度竞价

相关性算分

当我们利用match查询时,文档结果会根据与搜索词条的关联度打分(_score),返回结果时按照分值降序排列。相关性算分两种方式:

  • 1. TF-IDF:在elasticsearch5.0之前,会随着词频增加而越来越大
  • 2. BM25:在elasticsearch5.0之后,会随着词频增加而增大,但增长曲线会趋于水平

5.1 function score query

使用 function score query,可以修改文档的相关性算分(query score),根据新得到的算分排序。 

案例给“如家”这个品牌的酒店排名靠前一些

解析:function score需要的三要素 

1. 过滤条件:哪些文档需要算分加权?  答: 品牌为如家的酒店

2. 算分函数:算分函数是什么?   答:weight就可以

3. 加权方式:加权模式是什么?   答:求和

GET /hotel/_search
{"query":{"function_score": {"query": {"match": {"all": "外滩"}},"functions": [   #算分函数{ "filter": {   # 满足的条件,品牌必须是如家"term": {"brand": "如家"}},"weight": 2     #权重为2}],"boost_mode": "sum"}  }
}

 5.2 Boolean query

布尔查询是一个或多个查询子句的组合。子查询的组合方式有:

must:必须匹配每个子查询,类似“与”

should:选择性匹配子查询,类似“或”

must_not:必须不匹配,不参与算分,类似“非”

filter:必须匹配,不参与算分

需求搜索名字包含“如家”,价格不高于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}}}]}} 
}

二、搜索结果处理

1. 排序

elasticsearch支持对搜索结果排序,默认是根据相关度算分(_score)来排序。可以排序字段类型有:keyword类型、数值类型、地理坐标类型、日期类型等。

GET   /索引名/_search

{

  "query"{

    "match_all"{ }

  },

  "sort"[

    {

      "FIELD""desc"  // 排序字段和排序方式ASCDESC

    }

  ]

}

案例对酒店数据按照用户评价降序排序,评价相同的按照价格升序排序

# sort 排序
GET /hotel/_search
{"query": {"match_all": {}},"sort": [{"score": "desc"},{"price": "asc"}]
}

案例2实现对酒店数据按照到你的位置坐标的距离升序排序

获取经纬度的方式: 获取鼠标点击经纬度-地图属性-示例中心-JS API 2.0 示例 | 高德地图API

GET /hotel/_search
{"query": {"match_all": {}},"sort": [{"_geo_distance": {"location": {"lat": 31.064661,"lon": 121.621245},"order": "asc","unit": "km"}}]
}

结果:

2. 分页

elasticsearch 默认情况下值返回前10条数据,如果需要查询更多数据就需要修改分页参数了。

elasticsearch 中通过from, size参数来控制要返回分页结果。

GET /hotel/_search
{"query": {"match_all": {}},"sort": [{"price": "asc"}],"from": 0,  // 分页开始的位置,默认为0"size": 10   // 每页显示的条数
}

通过from, size 有个缺点,就是把所有数据都会查出来,然后通过截取的方式获取分页数据。对于海量数据,这种分页方式效率低下。也就是说,ES是分布式的,所以会面临深度分页问题。例如按price排序后,获取from = 990,size =10的数据:

  1. 首先在每个数据分片上都排序并查询前1000条文档。
  2. 然后将所有节点的结果聚合,在内存中重新排序选出前1000条文档
  3. 最后从这1000条中,选取从990开始的10条文档

如果搜索页数过深,或者结果集(from + size)越大,对内存和CPU的消耗也越高。因此ES设定结果集查询的上限是10000

针对深度分页,ES提供了两种解决方案,官方文档:

  • search after:分页时需要排序,原理是从上一次的排序值开始,查询下一页数据。官方推荐使用的方式。
  • scroll:原理将排序数据形成快照,保存在内存。官方已经不推荐使用。

结果处理集分页总结

from + size

•优点:支持随机翻页
•缺点:深度分页问题,默认查询上限(from + size)是10000
•场景:百度、京东、谷歌、淘宝这样的随机翻页搜索

after search

•优点:没有查询上限(单次查询的size不超过10000)
•缺点:只能向后逐页查询,不支持随机翻页
•场景:没有随机翻页需求的搜索,例如手机向下滚动翻页

scroll

•优点:没有查询上限(单次查询的size不超过10000)
•缺点:会有额外内存消耗,并且搜索结果是非实时的
•场景:海量数据的获取和迁移。从ES7.1开始不推荐,建议用 after search方案。

3. 高亮

高亮就是在搜索结果中把搜索关键字突出显示。

高亮原理解析:

  1. 将搜索关键字用标签标记起来。
  2. 在页面中给标签添加css样式

 

基本语法 

GET /索引库名/_search

{

  "query": {

    "match": {

      "FIELD""TEXT"

    }

  },

  "highlight": {

    "fields": { // 指定要高亮的字段

      "FIELD": {

        "pre_tags""<em>",  // 用来标记高亮字段的前置标签

        "post_tags""</em>" // 用来标记高亮字段的后置标签

      }

    }

  }

}

# 高亮显示,默认情况,ES搜索字段必须和高亮字段一致
GET /hotel/_search
{"query": {"match": {"all": "如家"}},"highlight": {"fields": {"name": {"require_field_match": "false"     #是否需要字段匹配,默认true,关闭后,   ES搜索字段可和高亮字段不一致 }}}
}

三、RestClient查询文档

1. 快速入门

通过match_all来演示下基本的API,先看请求DSL的组织:

通过match_all来演示下基本的API,解析结果:

详细代码

public class HotelSearchTest {private RestHighLevelClient client;// 客户端初始化@BeforeEachvoid setUp() {this.client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.30.130:9200")  // 服务器IP + ES 端口));}@Testvoid testMatchAll() throws IOException {// 1. 准备RequestSearchRequest request = new SearchRequest("hotel");// 2. 准备 DSLrequest.source().query(QueryBuilders.matchAllQuery());// 3. 发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);//4. 解析响应SearchHits hits = response.getHits();// 4.1 获取总条数long total = hits.getTotalHits().value;System.out.println("共搜索到" + total + "条数据");//4.2 文档数组SearchHit[] hits1 = hits.getHits();// 4.3 遍历for (SearchHit hit : hits1) {//获取文档sourceString json = hit.getSourceAsString();// 反序列化HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);System.out.println("hotelDoc = " + hotelDoc);}System.out.println(response);}@AfterEachvoid tearDown() throws IOException {this.client.close();}}

RestAPI中其中构建DSL是通过HighLevelRestClient中的resource()来实现的,其中包含了查询、排序、分页、高亮等所有功能。

 RestAPI中其中构建查询条件的核心部分是由一个名为QueryBuilders的工具类提供的,其中包含了各种查询方法:

2. match 查询

全文检索的matchmulti_match查询与match_allAPI基本一致。差别是查询条件,也就是query的部分。同样是利用QueryBuilders提供的方法:

// 单字段查询
QueryBuilders.matchQuery("all", "如家");
// 多字段查询
QueryBuilders.multiMatchQuery("如家", "name", "business");

// 查询所有
QueryBuilders.matchAllQuery();

match 查询

GET /hotel/_search

{

  "query": {

    "match": {

      "all""如家"

    }

  }

}

 match_all 查询

GET /hotel/_search

{

  "query": {

    "match_all": {}

  }

}

 @Testvoid testMatch() throws IOException {// 1. 准备RequestSearchRequest request = new SearchRequest("hotel");// 2. 准备 DSLrequest.source().query(QueryBuilders.matchQuery("all", "如家"));// 3. 发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);//4. 解析响应SearchHits hits = response.getHits();// 4.1 获取总条数long total = hits.getTotalHits().value;System.out.println("共搜索到" + total + "条数据");//4.2 文档数组SearchHit[] hits1 = hits.getHits();// 4.3 遍历for (SearchHit hit : hits1) {//获取文档sourceString json = hit.getSourceAsString();// 反序列化HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);System.out.println("hotelDoc = " + hotelDoc);}System.out.println(response);}

 

multi_match  查询

GET /hotel/_search

{

  "query": {

    "multi_match": {

      "query""如家",

      "fields": ["brand""name"]

    }

  }

}

@Testvoid testMultiMatch() throws IOException {// 1. 准备RequestSearchRequest request = new SearchRequest("hotel");// 2. 准备 DSLrequest.source().query(QueryBuilders.multiMatchQuery("如家", "name", "business"));// 3. 发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);//4. 解析响应SearchHits hits = response.getHits();// 4.1 获取总条数long total = hits.getTotalHits().value;System.out.println("共搜索到" + total + "条数据");//4.2 文档数组SearchHit[] hits1 = hits.getHits();// 4.3 遍历for (SearchHit hit : hits1) {//获取文档sourceString json = hit.getSourceAsString();// 反序列化HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);System.out.println("hotelDoc = " + hotelDoc);}System.out.println(response);}

 

3. 精确查询

精确查询常见的有term查询和range查询,同样利用QueryBuilders实现

// 词条查询
QueryBuilders.termQuery("city", "杭州");
// 范围查询
QueryBuilders.rangeQuery("price").gte(100).lte(150);

term 查询

GET /hotel/_search

{

  "query": {

    "term": {

      "city""杭州"

    }

  }

}

range 查询

GET /hotel/_search

{

  "query": {

    "range": {

      "price": { "gte"100"lte"150 }

    }

  }

}

@Testvoid testBool() throws IOException {// 1. 准备RequestSearchRequest request = new SearchRequest("hotel");//2. 准备DSL//2.1 准备BooleanQueryBoolQueryBuilder booledQuery = QueryBuilders.boolQuery();//2.2 添加 termbooledQuery.must(QueryBuilders.termQuery("city", "上海"));//2.3 添加rangebooledQuery.filter(QueryBuilders.rangeQuery("price").lte(250));request.source().query(booledQuery);// 3. 发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);//4. 解析响应SearchHits hits = response.getHits();// 4.1 获取总条数long total = hits.getTotalHits().value;System.out.println("共搜索到" + total + "条数据");//4.2 文档数组SearchHit[] hits1 = hits.getHits();// 4.3 遍历for (SearchHit hit : hits1) {//获取文档sourceString json = hit.getSourceAsString();// 反序列化HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);System.out.println("hotelDoc = " + hotelDoc);}System.out.println(response);}

 

4. 复合查询

复合查询——boolean query

// 创建布尔查询
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
// 添加must条件
boolQuery.must(QueryBuilders.termQuery("city", "杭州"));
// 添加filter条件
boolQuery.filter(QueryBuilders.rangeQuery("price").lte(250));

GET /hotel/_search

{

  "query": {

    "bool": {

      "must": [

        {

          "term": { "city""杭州" }

        }

      ],

      "filter": [

        {

          "range": {

            "price": { "lte"250 }

          }

        }

      ]

    }

  }

}

tips: 要构建查询条件,只要记住一个类:QueryBuilders 

@Testvoid testBool() throws IOException {// 1. 准备RequestSearchRequest request = new SearchRequest("hotel");//2. 准备DSL//2.1 准备BooleanQueryBoolQueryBuilder booledQuery = QueryBuilders.boolQuery();//2.2 添加 termbooledQuery.must(QueryBuilders.termQuery("city", "上海"));//2.3 添加rangebooledQuery.filter(QueryBuilders.rangeQuery("price").lte(250));request.source().query(booledQuery);// 3. 发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);//4. 解析响应SearchHits hits = response.getHits();// 4.1 获取总条数long total = hits.getTotalHits().value;System.out.println("共搜索到" + total + "条数据");//4.2 文档数组SearchHit[] hits1 = hits.getHits();// 4.3 遍历for (SearchHit hit : hits1) {//获取文档sourceString json = hit.getSourceAsString();// 反序列化HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);System.out.println("hotelDoc = " + hotelDoc);}System.out.println(response);}

5. 排序、分页

搜索结果的排序和分页是与query同级的参数,对应的API如下:

// 查询
request.source().query(QueryBuilders.matchAllQuery());

// 分页
request.source().from(0).size(5);

// 价格排序
request.source().sort("price", SortOrder.ASC);

// 距离排序
request.source().sort(SortBuilders
        .
geoDistanceSort("location", new GeoPoint("31.21, 121.5"))
        .order(SortOrder.
ASC)
        .unit(DistanceUnit.
KILOMETERS)
);

DSL 语句 

GET /indexName/_search

{

  "query": {

    "match_all": {}

  },

  "from"0,

  "size"5

  "sort": [

    {

      "FIELD""desc"  

    },

  ]

}

@Testvoid testPageAndSort() throws IOException {int page = 1, size = 5;// 1. 准备RequestSearchRequest request = new SearchRequest("hotel");//2. 准备DSL//2.1 queryrequest.source().query(QueryBuilders.matchAllQuery());//2.2 排序request.source().sort("price", SortOrder.ASC);//2.3 分页request.source().from((page - 1) * size).size(5);// 3. 发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);//4. 解析响应SearchHits hits = response.getHits();// 4.1 获取总条数long total = hits.getTotalHits().value;System.out.println("共搜索到" + total + "条数据");//4.2 文档数组SearchHit[] hits1 = hits.getHits();// 4.3 遍历for (SearchHit hit : hits1) {//获取文档sourceString json = hit.getSourceAsString();// 反序列化HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);System.out.println("hotelDoc = " + hotelDoc);}System.out.println(response);}

6. 高亮

高亮API包括请求DSL构建和结果解析两部分。我们先看请求的DSL构建:

request.source().highlighter(new HighlightBuilder()
        .field(
"name")
       
// 是否需要与查询字段匹配
       
.requireFieldMatch(false)
);

DSL 语句

GET /hotel/_search

{

  "query": {

    "match": {

      "all""如家"

    }

  },

  "highlight": {

    "fields": {

      "name": {

        "require_field_match""false"

      }

    }

  }

}

 

高亮结果解析

// 获取source
HotelDoc hotelDoc = JSON.parseObject(hit.getSourceAsString(), 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);
    }
}

关键字:乌鲁木齐市电话号码黄页_深圳形象设计公司_腾讯新闻最新消息_精品成品网站源码

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: