ElasticSearch DSL查询、排序 、分页的原理及语法

1. DSL查询分类和基本语法

ElasticSearch提供了基于Json的DSL来定义查询,常见的查询类型包括:
• 查询所有:查询出所有数据,一般测试用,一般不是查出所有,一次性查询20条。例如 match_all
• 全文检索(full text)查询:利用分词器对用户输入内容分词,然后去倒排索引中匹配,例如:
match_query、mutil_match_query
• 精确查询:根据精确词条查找数据,一般查找keyword、数值、日期、boolean等类型字段。例如:
ids、range(数字或者日期范围)、term(具体的某一个数字);
• 地理(geo)查询:根据经纬度查询。例如:
geo_diatance、geo_bounding_box
• 复合查询,复合查询可以将上述各种查询条件组合几来,合并查询条件,例如:
bool、function_score。

2. DSL全文检索查询语句

会对用户输入内容分词,常用于搜索框搜索。
match:根据一个字段查询,会对用户输入内容分词,然后去倒排索引库检索,语法:

GET/indexName/_search{
"query":{
     "match"{   #  查询方式,全文检索
        "FIELD":"TEXT"  # 字段:查询文本
            }
        }
}

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

Get/indexName/_search
{
"query":{
    "multi_match":{
        "query": "text",
        "fields": ["field1", "field2"]
            }
      }
}

如果想要查询多个字段,建议使用match,将多个字段使用copy to的方式拷贝到一个字段中去,创建一个新的字段名。

3. DSL精确查询语句

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

Get/indexName/_search
{
    "query":{
        "term"{
           "FIELD"{
               "value": "value"
            }
        }
    }
}

range:根据值范围查询,例如根据日期,数值类型查询,语法如下:

Get/indexName/_search
{
  “query”:{
    "range":{
      "FIELD":{
          "gte": 10,
          "lte": 20
        }
      }
   }
}
4 .DSL地理查询语句

根据经纬度查询。常见得场景有:
• 携程:搜索我附近的酒店。
• 滴滴:搜索我附近的滴滴。
• 微信:收缩我附近的人。
地理查询的方式有很多总,如下:
• geo_bounding_box:查询geo_point 值落在某个矩形范围的所有文档,语法如下:

GET /indexName/search
{
      "query":{
          "geo_bounding_box":{
                  "FIELD":{
                      "top_left":{
                          "lat": 31.1,
                          "lon": 121.5
                  },
                      "bottom_right":{
                         "lat": 30.9,
                         "lon": 121.7
                 }
              }
          }
      }
}

top_left 和bottom_right代表地图上的两个点,以两个点为准,画出一个矩形,查询的是在矩形范围内的文档,如下图所示:
在这里插入图片描述
geo_distance:查询到指定中心点小于某个距离值的所有文档,语法如下:

GET /indexName/_search
{
   "query":{
        "geo_distance":{
                "distance:"15km",    ## 距离
                "FIELD": "31.21,121.5"   ## 中心点
               }
        }
}

如下图所示,查询的就是以31.21,121.5为中心点,小于15Km范围内的所有文档,适合用于查询附近的人的场景:
在这里插入图片描述

5. DSL复合查询

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

5.1 function score

算分函数查询,可以控制文档相关性算分,控制文档排名。例如,当我们利用match查询时,文件结果会根据与搜索词条的关联度打分,返回结果时按照分值降序排列。
如下图所示,我们搜索 “虹桥如家”,结果如下,会发现包含虹桥如家的分数最高,排在最前面。
在这里插入图片描述

打分的算法如下图所示:
在这里插入图片描述
ES中使用的是BM25算法,BM25算法相对于TF-IDF算法的优势就是,随着词频不断增加,相关性算分不会无限增加,而TF-IDF算法随着词频不断增加,相关性算分会不断无限增加,如下图所示:
在这里插入图片描述
总结:ES中的相关性打分算法在ES5.0之前采用的是TF-IDF,会随着词频增加而越来越大,在ES5.0之后,采用BM25,会随着词频增加而不断增大,但增长曲线会趋于水平。
上面介绍了ES的相关性打分,但是我们可以根据需求修改文档的相关性算分,人为控制排名,根据新得到的算分排序,就需要讲解function score query

5.2 复合查询- function score query

语法:

GET /hotel/_search
{
  "query":{
    "function score":{
      "query":{"match":{"all":"外滩"}}, ## 原始查询条件,搜索文档并根据相关性打分(query score)
      "functions":[
               {
                  "filter": {"term":{"id":"1"}},  ## 过滤条件,复合条件的文档才会被重新算分,例如这里是id为1的会重新算分
                  "weight": 10  
                  ## 算分函数,算分函数的结果称为function score,将来会与query score 运算,得到新的算分,常见的算分函数有
                  ## 1.weight:给一个常量值,作为函数结果(function score);
                  ## 2.field_value_factor:用文档中的某个字段值作为函数结果;
                  ## 3. random_score:随机生成一个值,作为函数结果;
                  ## 4. script_socre:自定义计算公式,公式结果作为函数结果
               }
             ],
           "boost mode":"multiply"
           ## 加权模式,定义function score与query score的运算方式,包括:
           ## 1.multiply:两者相乘。默认就是这个;
           ## 2.replace:用function score 替换 query score;
           ## 3.其他:sum、avg、max、min。
       }
    }
 }

案例:给“如家”这个品牌的酒店排名靠前一些。我们需要考虑function score的三要素:
• 哪些文档需要算分加权?这里就是对应的filter,品牌为如家的需要过滤。
• 算分函数是什么?这里我们可以选择weight算分函数。
• 加权模式是什么?这里对应的就是boost_mode,我们可以选择multiply。
查询语句如下:

GET /hotel/_search
{
 "query":{"
   function_score":{
     "query":{//..·},
     "functions":[ // 算分函数
       "filter":{ // 满足的条件,品牌必须是如家
         "term":{
           "brand":"如家"
           }
         },
       "weight":2 // 算分权重为2
       }
     },
    "boost_mode": "sum"
    }
  }
}
4.5.3 复合查询-Boolean Query

复合查询中的布尔查询是一个或多个查询子句的组合。子句的组合方式有:
• must:必须匹配每个子查询,类似“与”;
• should:选择性匹配子查询,类似“或”;
• must_not : 必须不匹配,不参与算分,类似 “非”;
• filter:必须匹配,不参与算分。
案例,如下图所示:
在这里插入图片描述

6. DSL搜索结果处理
6.1 排序

ES支持对搜索结果的排序,默认是根据相关度算分来排序。一旦指定自己的排序字段,ES就放弃相关度算分,查询的效率也会提升。可以排序的字段类型有:keyword类型、数值类型、地理坐标类型、日期类型等。
keyword类型、数值类型、日期类型排序语法:

GET /indexName/_search
{
"query":{
    "match_all":{}
    },
"sort":[
   {
    "FIELD1": "desc"//排序字段和排序方式ASC、DESC
    },
    {
    "FIELD2": "asc"//排序字段和排序方式ASC、DESC
     }
    ]
  }

根据地理坐标排序语法:

GET /indexName/search
{
 "query":{
   "match_all":{}
  },
 "sort":[
  {
   "_geo_distance" :{
           "FIELD1":"纬度,经度",
            "order" : "asc",
            "unit" :"km"
          }
       }
    ]
}
6.2 分页

ES默认情况下只返回top 10条数据。而如果要查询更多数据就需要修改分页参数了。
ES中通过修改from 、size参数来控制要返回的分页结果,语法如下:

GET /hotel/_search
{
  "query": {
     "match_all": {}
   },
   "from":990,## 分页开始的位置,默认为0;
   "size":10,## 期望获取的文档总数
   "sort":[
         {"price": "asc"}
    ]
}

ES分页使用虽然跟mysql很像,只需要指定from,size即可,但原理和mysql存在较大的差异,ES分页的原理采用的是一种逻辑分页,假如现在
需要查990到1000的文档数据,如下图所示,ES会查出从0-1000的所有数据,然后截出990-1000的文档数据:
在这里插入图片描述
上面这种截取方式对于单个节点的ES是没有问题的,但是在实际情况下,为了能够存储更多的数据,那么ES是会进行集群部署的,一旦进行集群,ES就会对文档数据进行拆分,放到不同的机器上,如下图所示:
在这里插入图片描述
ES是分布式的,所以会面临深度分页的问题,例如现在按照price字段排序后,获取from = 990, size = 10的数据,那么就会获取0到1000的文档数据,然后截取,但是现在有多个ES集群部署了,如果只是截取某一台0-1000数据文档的10条数据那么就存在问题。ES集群情况下分页截取的原理如下:
• 首先在每个集群数据分片上都排序并查询前1000条文档;
• 然后将所有节点的结果聚合,在内存中重新排序选出前1000条文档;
• 最后从这1000条中,选取从990开始的10条文档。

如果搜索页数过深,或者结果集(from+size)越大,对内存和CPU的消耗也越高。因此ES设定结果集查询的上限是10000,一旦超过10000,就会报错,一般我们在实际情况中,从业务层面就限定查询不能超过10000条,如果实际的业务就要查询超过10000条,ES提供了两种解决办法:
• search after:分页时需要排序,原理是从上一次的排序字段后的末尾值开始,走位查询条件,查询下一页数据,分页只能往后翻,不能往前翻。官方推荐使用的方式;
• scroll:原理将排序数据形成快照,保存在内存,对内存消耗非常大。官方已经不推荐使用。

总结:
from + size:
• 优点:支持随机翻页;
• 缺点:深度分页问题,默认查询上限(from+size)是10000场景;
• 百度、京东、谷歌、淘宝这样的随机翻页搜索。
after search :
• 优点:没有查询上限(单次查询的size不超过10000);
• 缺点:只能向后逐页查询,不支持随机翻页;
• 场景:没有随机翻页需求的搜索,例如手机向下滚动翻页。
scroll:
• 优点:没有查询上限(单次查询的size不超过10000);
• 缺点:会有额外内存消耗,并且搜索结果是非实时的
• 场景:海量数据的获取和迁移。从ES7.1开始不推荐,建议用 aftersearch方案。

6.3 高亮

就是在搜索结果中把搜索关键字突出显示。
原理如下:
• 将搜索结果中的关键字用标签标记出来
• 在页面中给标签添加css样式
语法如下:

GET /hotel/_search
{
  "query":{
    "match" :{
      "FIELD": "TEXT"
    }
 },
"highlight": {
 "fields":{ ## 指定要高亮的字段
  "FIELD":{
    "pre_tags": "<em>", ## 用来标记高亮字段的前置标签
    "post_tags":"</em>” ## 用来标记高亮字段的后置标签
    }
   }
  }
 }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/401547.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RMAN备份与恢复

文章目录 一、RMAN介绍二、全量备份三、增量备份0级备份1级增量备份累积性差量备份总结 四、压缩备份压缩备份介绍压缩备份操作压缩备份优缺点 五、异常恢复1、恢复前的准备2、恢复数据库 六、RMAN相关参数 一、RMAN介绍 RMAN&#xff08;Recovery Manager&#xff09;是Oracl…

Oracle:一条SQL在Oracle中的执行过程流程

一条SQL在Oracle中执行过程流程如下图&#xff1a;

QT-Day1

思维导图 作业 自由发挥登录窗口的应用场景&#xff0c;实现一个登录窗口界面。 #include "widget.h"Widget::Widget(QWidget *parent): QWidget(parent) {//窗口this->setWindowTitle("QQ");this->setWindowIcon(QIcon("D:\\study\\hqyj\\co…

【PX4-AutoPilot教程-TIPS】PX4控制无人机在Gazebo中飞行时由于视角跟随无人机在画面中心导致视角乱晃的解决方法

PX4控制无人机在Gazebo中飞行时由于视角跟随无人机在画面中心导致视角乱晃的解决方法 问题描述解决方法 问题描述 无人机在Gazebo中飞行时&#xff0c;无人机始终处于画面中央&#xff0c;会带着视角乱晃&#xff0c;在Gazebo中进行任何操作视角都无法固定。 观察Gazebo左侧Wo…

【JavaEE】_ajax构造HTTP请求

目录 1. ajax简述 2. ajax构造HTTP请求 2.1 jquery库的引入 2.2 ajax构造HTTP请求格式 3. ajax构造GET请求实例 4. ajax构造POST请求实例 本专栏关于form表单构造HTTP请求一文中已经提到&#xff1a;form表单构造法只支持GET和POST&#xff0c;且会触发页面跳转。 原文详…

线上线下同时开店管理混乱?EasyBoss ERP升级线下零售订单功能帮你轻松搞定

许多做东南亚本土电商的卖家&#xff0c;会将线下店铺作为业绩增长的一个重要渠道&#xff0c;但是在运营过程中会出现&#xff1a;需要使用多个系统、库存不同步、数据混乱等问题&#xff0c;为了帮助卖家解决这些问题&#xff0c;EasyBoss此前已开发线下零售订单功能&#xf…

【Linux】再谈进程地址空间

目录 一、引入 二、物理内存和外设空间的交互 三、解决页表过大问题 一、引入 我们在往期的博客中有讲解过进程地址空间&#xff1a;【Linux】进程地址空间 但是在上述博客中我们只是对进程地址空间的左边部分详细进行了讲解&#xff0c;下面我们就来谈谈右边的部分&#…

支付功能设计及实现思路

支付功能设计 主要包括&#xff1a;订单表&#xff0c;订单日志表&#xff0c;订单队列&#xff0c;定时任务。 主要考虑&#xff1a;事务性、幂等性、安全性。 表结构设计 订单表&#xff1a; 订单表&#xff0c;最主要的就是订单号、支付状态。 CREATE TABLE t_order (…

十大基础排序算法

排序算法分类 排序&#xff1a;将一组对象按照某种逻辑顺序重新排列的过程。 按照待排序数据的规模分为&#xff1a; 内部排序&#xff1a;数据量不大&#xff0c;全部存在内存中&#xff1b;外部排序&#xff1a;数据量很大&#xff0c;无法一次性全部存在内存中&#xff0c;…

Backtrader 文档学习- 整体架构功能分析理解

Backtrader 文档学习- 架构功能分析理解 1. 概述 backtrader是一个用于开发和执行交易策略的Python框架。它提供了一套完整的工具和功能&#xff0c;使得用户可以方便地进行策略回测、实盘交易以及数据分析。 backtrader的入口为Cerebro类&#xff0c;该类将所有输入(Data F…

基于Jenkins实现的CI/CD方案

基于Jenkins实现的CI/CD方案 前言 最近基于Jenkins的基座&#xff0c;搭建了一套适用于我们项目小组的持续集成环境。现在把流程整理分享出来&#xff0c;希望可以给大家提供一些帮助和思路。 使用到的组件和版本 组件名称组件版本作用Harbor2.7.3镜像仓库Jenkins2.319.2持…

C++ Primer 笔记(总结,摘要,概括)——第5章 语句

目录 5.1 简单语句 5.2 语句作用域 5.3 条件语句 5.3.1 if语句 5.3.2 switch语句 5.4 迭代语句 5.4.1 while语句 5.4.2 传统的for语句 5.4.3 范围for语句 5.4.4 do while语句 5.5 跳转语句 5.5.1 break语句 5.5.2 continue语句 5.5.3 goto语句 5.6 try语句块和异常处理 5…

http和https的区别(简述)

HTTP&#xff08;HyperText Transfer Protocol&#xff09;和HTTPS&#xff08;HTTP Secure&#xff09;都是用于在客户端和服务器之间传输数据的协议&#xff0c;但它们在安全性方面有重要的区别。 1.HTTP: 概述&#xff1a; HTTP是一种用于传输超文本的协议&#xff08;超文…

前端基础自学整理|DOM树

DOM&#xff0c;文档对象模型&#xff08;Document Object Model&#xff09;&#xff0c;简单的说&#xff0c;DOM是一种理念&#xff0c;一种思想&#xff0c;一个与系统平台和编程语言无关的接口&#xff0c;一种方法, 使 Web开发人员可以访问HTML元素&#xff01;不是具体方…

D6208——双向马达驱动电路芯片,噪声低 内设马达驱动功率晶体管,工作电源电压范围宽用 TTL 逻辑信号直接控制

D6208 是一块单片双向马达驱动电路&#xff0c;它使用TTL电平的逻辑信号就能控制卡式录音机和其它电子设备中的双向马达。该电路由一个逻辑部分和一个功率输出部分组成。逻辑部分控制马达正、反转向及制动&#xff0c;功率输出部分根据逻辑控制能提供100mA&#xff08;典型值&a…

【python】 脚本检查文本里是否包含特殊字符

【python】 脚本检查文本里是否包含特殊字符 完整代码&#xff1a; # 代码片段功能: 检查文本里是否包含特殊字符 # 将utf-8格式文本&#xff0c;先转为16进制格式 # 检查完成&#xff0c;再将16进制格式转为utf-8格式。 import re# 包含特殊字符的字符串 sample "I arg…

当别人在用AI一分钟画几十张图,你还在埋头苦苦设计?AI时代一定要学会和AI共存!

AI绘画即指人工智能绘画&#xff0c;是一种计算机生成绘画的方式。是AIGC应用领域内的一大分支。 AI绘画主要分为两个部分&#xff0c;一个是对图像的分析与判断&#xff0c;即“学习”&#xff0c;一个是对图像的处理和还原&#xff0c;即“输出”。 人工智能通过对数以万计…

数据分析(二)自动生成分析报告

1. 报告生成思路概述 怎么快速一份简单的数据分析报告&#xff0c;注意这个报告的特点&#xff1a; --网页版&#xff0c;可以支持在线观看或者分享HTML文件 --标题&#xff0c;动图&#xff0c;原始数据应有尽有 --支持交互&#xff0c;比如plotly交互画面&#xff0c;数据…

Windows安装PHP及在VScode中配置插件,使用PHP输出HelloWorld

安装PHP PHP官网下载地址(8.3版本)&#xff1a;PHP For Windows&#xff1a;二进制文件和源代码发布 点击下载.zip格式压缩包&#xff1a; 历史版本在Old archives中下载。推荐在Documentation download中下载官方文档&#xff0c;方便学习。 下载完成后在一个顺眼的地方解压压…

net反射

1.1 查找dll文件 Load需要把dll放到程序当前路径加载&#xff0c;也可以读取字符串形式。LoadFrom需要写全路径&#xff0c;如果test1.dll引用了test2.dll&#xff0c;同时也会加载test2.dll进来。LoadFile不会加载test2.dll。 Assembly assembly1 Assembly.Load("DllTe…