【Elasticsearch】学习笔记-p4(DSL查询文档)

【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】

**开源地址:https://docs.qq.com/doc/DSmxTbFJ1cmN1R2dB **

  • match:根据一个字段查询

  • multi_match:根据多个字段查询,参与查询字段越多,查询性能越差

3.精准查询


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

  • term根据词条精确值查询

  • range根据值的范围查询

3.1 term查询

因为精确查询的字段搜是不分词的字段,因此查询的条件也必须是不分词的词条。查询时,用户输入的内容跟自动值完全匹配时才认为符合条件。如果用户输入的内容过多,反而搜索不到数据。

语法说明:

// term查询

GET /indexName/_search

{

“query”: {

“term”: {

“FIELD”: {

“value”: “VALUE”

}

}

}

}

例子:

#term查询

GET /hotel/_search

{

“query”: {

“term”: {

“city”: {

“value”: “上海”

}

}

}

}

3.2 range查询

范围查询,一般应用在对数值类型做范围过滤的时候。比如做价格范围过滤。

基本语法:

// range查询

GET /indexName/_search

{

“query”: {

“range”: {

“FIELD”: {

“gte”: 10, // 这里的gte代表大于等于,gt则代表大于

“lte”: 20 // lte代表小于等于,lt则代表小于

}

}

}

}

示例:

#range查询

GET /hotel/_search

{

“query”: {

“range”: {

“price”: {

“gt”: 249,

“lte”: 300

}

}

}

}

4.地理坐标查询


所谓的地理坐标查询,其实就是根据经纬度查询

常见的使用场景包括:

  • 携程:搜索我附近的酒店

  • 滴滴:搜索我附近的出租车

  • 微信:搜索我附近的人

4.1 矩形范围查询

矩形范围查询:也就是geo_bounding_box查询,查询坐标落在某个矩形范围的所有文档:

img

查询时,需要指定矩形的左上右下两个点的坐标,然后画出一个矩形,落在该矩形内的都是符合条件的点。

语法如下:

// geo_bounding_box查询

GET /indexName/_search

{

“query”: {

“geo_bounding_box”: {

“FIELD”: {

“top_left”: { // 左上点

“lat”: 31.1,

“lon”: 121.5

},

“bottom_right”: { // 右下点

“lat”: 30.9,

“lon”: 121.7

}

}

}

}

}

4.2 附近查询

附近查询:也叫做距离查询(geo_distance):查询到指定中心点小于某个距离值的所有文档。

换句话来说,在地图上找一个点作为圆心,以指定距离为半径,画一个圆,落在圆内的坐标都算符合条件:

img

语法说明:

// geo_distance 查询

GET /indexName/_search

{

“query”: {

“geo_distance”: {

“distance”: “15km”, // 半径

“FIELD”: “31.21,121.5” // 圆心

}

}

}

例子:

我们先搜索陆家嘴附近15km的酒店:

img

发现共有47家酒店,然后把半径缩短到3公里:

img

可以发现,搜索到的酒店数量减少到了5家。

5.复合查询


复合查询:复合查询可以将其它简单查询组合起来,实现更复杂的搜索逻辑。常见的有两种:

  • fuction score算分函数查询,可以控制文档相关性算分,控制文档排名

  • bool query布尔查询,利用逻辑关系组合多个其它的查询,实现复杂搜索

5.1 相关性算分(了解)

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

例如,我们搜索 “虹桥如家”,结果如下:

[

{

“_score” : 17.850193,

“_source” : {

“name” : “虹桥如家酒店真不错”,

}

},

{

“_score” : 12.259849,

“_source” : {

“name” : “外滩如家酒店真不错”,

}

},

{

“_score” : 11.91091,

“_source” : {

“name” : “迪士尼如家酒店真不错”,

}

}

]

elasticsearch中,早期使用的打分算法是TF-IDF算法,公式如下:

img

在后来的5.1版本升级中,elasticsearch将算法改进为BM25算法,公式如下:

img

TF-IDF 算法有一各缺陷,就是词条频率越高,文档得分也会越高,单个词条对文档影响较大。而 BM25 则会让单个词条的算分有一个上限,曲线更加平滑:

img

小结:elasticsearch会根据词条和文档的相关度做打分,算法由两种:

  • TF-IDF算法

  • BM25算法,elasticsearch5.1版本后采用的算法

5.2 算分函数查询

根据相关度打分是比较合理的需求,但有时候也不能够满足我们的需求。

以百度为例,你搜索的结果中,并不是相关度越高排名越靠前,而是谁给的钱多排名就越靠前:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DATbGhrZ-1637137622217)(file://C:\Users\30287\Desktop\Java%E5%AD%A6%E4%B9%A0%E8%A7%86%E9%A2%91\day03-Docker\day06-Elasticsearch02%E8%AE%B2%E4%B9%89\assets\image-20210721191144560.png?lastModify=1637136892)]

(1)function score

要想认为控制相关性算分,就需要利用elasticsearch中的function score 查询了

img

function score 查询中包含四部分内容:

  • 原始查询条件:query部分,基于这个条件搜索文档,并且基于BM25算法给文档打分,原始算分(query score)

  • 过滤条件:filter部分,符合该条件的文档才会重新算分

  • 算分函数:符合filter条件的文档要根据这个函数做运算,得到的函数算分(function score),有四种函数:

  • weight:函数结果是常量

  • field_value_factor:以文档中的某个字段值作为函数结果

  • random_score:以随机数作为函数结果

  • script_score:自定义算分函数算法

  • 运算模式:算分函数的结果、原始查询的相关性算分,两者之间的运算方式,包括:

  • multiply:相乘

  • replace:用function score替换query score

  • 其它,例如:sum、avg、max、min

function score的运行流程如下:

  1. 根据原始条件查询搜索文档,并且计算相关性算分,称为原始算分(query score)

  2. 根据过滤条件,过滤文档

  3. 符合过滤条件的文档,基于算分函数运算,得到函数算分(function score)

  4. 原始算分(query score)和函数算分(function score)基于运算模式做运算,得到最终结果,作为相关性算分

因此,其中的关键点是

  • 过滤条件:决定哪些文档的算分被修改

  • 算分函数:决定函数算分的算法

  • 运算模式:决定最终算分结果

(2)例子

需求:给“如家”这个品牌的酒店排名靠前一些

翻译一下这个需求,转换为之前说的四个要点:

  • 原始条件:不确定,可以任意变化

  • 过滤条件:brand = “如家”

  • 算分函数:可以简单粗暴,直接给固定的算分结果,weight

  • 运算模式:比如求和

因此最终的DSL语句如下:

GET /hotel/_search

{

“query”: {

“function_score”: {

“query”: { … }, // 原始查询,可以是任意条件

“functions”: [ // 算分函数

{

“filter”: { // 满足的条件,品牌必须是如家

“term”: {

“brand”: “如家”

}

},

“weight”: 2 // 算分权重为2

}

],

“boost_mode”: “sum” // 加权模式,求和

}

}

}

测试,在未添加算分函数时,如家得分如下:

img

添加了算分函数后,如家得分就提升了:

img

5.3 布尔查询

(1)定义

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

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

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

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

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

比如在搜索酒店时,除了关键字搜索外,我们还可能根据品牌、价格、城市等字段做过滤:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值