ElasticSearch学习笔记(三)RestClient操作文档、DSL查询文档、搜索结果排序

文章目录

  • 前言
  • 5 RestClient操作文档
    • 5.4 删除文档
    • 5.4 修改文档
    • 5.5 批量导入文档
  • 6 DSL查询文档
    • 6.1 准备工作
    • 6.2 全文检索查询
    • 6.3 精准查询
    • 6.4 地理坐标查询
    • 6.5 复合查询
      • 6.5.1 相关性算分
      • 6.5.2 布尔查询
  • 7 搜索结果处理
    • 7.1 排序
      • 7.1.1 普通字段排序
      • 7.1.2 地理坐标排序

前言

ElasticSearch学习笔记(一)倒排索引、ES和Kibana安装、索引操作
ElasticSearch学习笔记(二)文档操作、RestHighLevelClient的使用

5 RestClient操作文档

5.4 删除文档

删除文档的DSL语句示例如下:

DELETE /hotel/_doc/2

对应的Java代码如下:

@Test
public void testDeleteHotelDoc() throws IOException {// 1.创建Request对象DeleteRequest request = new DeleteRequest("hotel", "2");// 2.发送请求client.delete(request, RequestOptions.DEFAULT);
}

执行以上单元测试,在DevTools工具中查询该文档:

5.4 修改文档

上一节已经了解到,修改文档有全量修改增量修改两种方式。

在RestClient的API中,全量修改与新增文档的API完全一致,判断依据是文档ID是否已存在:

  • 新增时,如果ID已存在,则修改;
  • 如果ID不存在,则新增。

而增量修改是修改文档中指定的字段值,其DSL语句示例如下:

POST /hotel/_update/2
{"doc": {"address": "中山大道"}
}

对应的Java代码如下:

@Test
public void testUpdateHotelDoc() throws IOException {// 1.创建Request对象UpdateRequest request = new UpdateRequest("hotel", "2");// 2.设置要修改的字段request.doc("address", "中山大道");// 3.发送请求client.update(request, RequestOptions.DEFAULT);
}

执行以上单元测试,在DevTools工具中查询该文档:

5.5 批量导入文档

RestClient提供了一个BulkRequest类用于批量导入文档,其本质就是将多个普通的CRUD请求组合在一起发送,主要使用其add()方法:

可见,能添加的请求包括IndexRequest(新增)、UpdateRequest(修改)、DeleteRequest(删除)等。

对应的Java代码如下:

@Test
public void testBulkHotelDoc() throws IOException {// 1.创建Request对象BulkRequest request = new BulkRequest();// 2.准备参数List<Hotel> hotelList = hotelService.list();for (Hotel hotel : hotelList) {HotelDoc hotelDoc = new HotelDoc(hotel);request.add(new IndexRequest("hotel").id(hotelDoc.getId().toString()).source(JSON.toJSONString(hotelDoc), XContentType.JSON));}// 3.发送请求client.bulk(request, RequestOptions.DEFAULT);
}

执行以上单元测试,在DevTools工具中查询该文档:

6 DSL查询文档

6.1 准备工作

首先,向tb_hotel表插入大量数据,例如下图显示已经查了201条数据:

然后执行以下单元测试testSaveBatchHotelDoc()方法,将数据库的数据存储到ES中:

@Test
public void testSaveBatchHotelDoc() throws IOException {// 1.查询酒店数据,遍历处理List<Hotel> hotelList = hotelService.list();for (Hotel hotel : hotelList) {// 2.转换为文档类型HotelDoc hotelDoc = new HotelDoc(hotel);// 3.将HotelDoc转jsonString json = JSON.toJSONString(hotelDoc);// 4.准备Request对象IndexRequest request = new IndexRequest("hotel").id(hotelDoc.getId().toString());// 5.准备Json文档request.source(json, XContentType.JSON);// 6.发送请求client.index(request, RequestOptions.DEFAULT);}
}

执行完毕后,可以在Kibana中看到此时hotel索引中有201个文档:

6.2 全文检索查询

ES的查询是基于JSON的DSL查询。而全文检索查询就是利用分词器对用户输入的内容进行分词,然后去倒排索引库中匹配,例如电商系统的商品搜索、百度关键词搜索等。

其基本流程如下:

  • 1)对用户输入的内容进行分词,得到词条;
  • 2)根据词条去倒排索引中匹配,得到文档id;
  • 3)根据文档id找到文档,返回给用户。

常见的全文检索查询包括:

  • match:单字段查询
  • multi_match:多字段查询,任意一个字段符合条件就算符合查询条件

其DSL语句示例如下:

# match查询
GET /hotel/_search
{"query": {"match": {"all": "外滩如家"}}
}# multi_match查询
GET /hotel/_search
{"query": {"multi_match": {"query": "外滩如家","fields": ["brand", "name", "business"]}}
}

例如:

可以看到,两种查询结果是一样的,这是因为在索引hotelbrandnamebusiness三个字段利用copy_to复制到了all字段中。因此根据这三个字段搜索,和根据all字段搜索效果是一样的。

因此,使用multi_match查询时,搜索字段越多,对查询性能影响越大,建议采用copy_to将多个字段复制到一个字段中,然后单字段查询的方式。

6.3 精准查询

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

常见的精准查询类型有:

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

其DSL语句示例如下:

# term查询
GET /hotel/_search
{"query": {"term": {"city": {               //要查询的字段"value": "上海"     //字段值}}}
}# range查询
GET /{索引名}/_search
{"query": {"range": {"price": {              //要查询的字段"gte": 1000,        // >=1000"lte": 3000         // <=3000}}}
}

例如:

term查询时,当搜索的内容不是词条,而是多个词语形成的短语时,反而搜索不到:

range查询例子:

6.4 地理坐标查询

地理坐标查询,就是根据经纬度查询,常见的场景有滴滴搜索附近的出租车、微信搜索附近的人等。

常见的地理坐标查询类型有:

  • geo_bounding_box:矩阵范围查询,即查询坐标落在某个矩形范围的所有文档。查询时,需要指定矩形的左上右下两个点的坐标,然后画出一个矩形,落在该矩形内的都是符合条件的点。
  • geo_distance:附近查询,也叫距离查询,查询到指定中心点小于某个距离值的所有文档。也就是在地图上找一个点作为圆心,以指定距离为半径,画一个圆,落在圆内的坐标都算符合条件。

其DSL语句示例如下:

# geo_bounding_box查询
GET /hotel/_search
{"query": {"geo_bounding_box": {"location": {                   //要查询的字段"top_left": {               //左上点"lat": "32.00",         //左上点纬度"lon": "120.00"         //左上点经度},"bottom_right": {           //右下点"lat": "30.00",         //右下点纬度"lon": "122.00"         //右下点经度}}}}
}# geo_distance查询
GET /hotel/_search
{"query": {"geo_distance": {"distance": "10km",             //半径"location": "30.00,122.00"      //要查询的字段:圆心坐标}}
}

例如:

6.5 复合查询

复合查询,就是将其它简单查询组合起来,实现更复杂的搜索逻辑。

常见的符合查询有两种:

  • fuction_score:算分函数查询,可以控制文档相关性算分,控制文档排名
  • bool query:布尔查询,利用逻辑关系组合多个其它的查询,实现复杂搜索

6.5.1 相关性算分

在前面的match查询时,查询结果会根据与搜索词条的关联度打分(_score),返回结果时按照分值降序排列。

根据相关度打分再进行排序是比较合理的,但并不一定是项目需要的。

如果想人为控制相关性算分,就需要利用ES中的function score查询。

其基本语法如下:

  • query:原始查询条件,基于这个条件搜索文档并给文档打分,这个分数叫原始算分(query score)
  • filter:过滤条件,符合该条件的文档才会重新算分
  • 算分函数:符合filter条件的文档要根据这个函数做运算,得到的函数算分(function score),有四种函数:
    • weight:函数结果是常量
    • field_value_factor:以文档中的某个字段值作为函数结果
    • random_score:以随机数作为函数结果
    • script_score:自定义算分函数算法
  • boost_mode:运算模式,即原始算分和函数算分两者之间的运算方式,包括:
    • multiply:相乘
    • replace:用function score替换query score
    • sum、avg、max、min等

function score查询的基本流程如下:

  • 1)根据原始条件搜索文档,并且计算原始算分(query score);
  • 2)根据过滤条件,过滤文档;
  • 3)符合过滤条件的文档,基于算分函数运算,得到函数算分(function score);
  • 4)将原始算分(query score)和函数算分(function score)基于运算模式做运算,得到最终结果,作为相关性算分。

例如有如下需求:让上海的“如家”这个品牌的酒店排名靠前一些。该需求转换为function score查询的要点如下:

  • 原始条件:city = “上海”
  • 过滤条件:brand = “如家”
  • 算分函数:直接给固定的算分结果,weight
  • 运算模式:求和

最终的DSL语句如下:

# function score查询
GET /hotel/_search
{"query": {"function_score": {"query": {"match": {"city": "上海"}},"functions": [{"filter": {"term": {"brand" : "如家"}},"weight": 2 //算分权重为2}],"boost_mode": "sum" //加权模式,求和}}
}

原始查询的结果如下:

使用function score查询的结果如下:

6.5.2 布尔查询

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

子查询的组合方式有:

  • must:必须匹配每个子查询,类似“与”
  • should:选择性匹配子查询,类似“或”
  • must_not:必须不匹配,不参与算分,类似“非”
  • filter:必须匹配,不参与算分

比如在搜索酒店时,除了根据关键字搜索外,还可能根据品牌、价格、城市等字段进行过滤。由于这些字段的查询方式各不相同,因此就需要用到布尔查询。

需要注意的是,进行布尔搜索时,参与打分的字段越多,查询的性能也越差。因此布尔查询一般建议:

  • 搜索框的关键字搜索,是全文检索查询,使用must查询,参与算分;
  • 其它过滤条件,采用filter查询,不参与算分。

例如有如下需求:搜索名字包含“如家”,价格不高于400,在坐标(31.21,121.5)周围10km范围内的酒店。该需求转换为布尔查询的要点如下:

  • 名称搜索,属于全文检索查询,应该参与算分,放到must中;
  • 价格不高于400,用range查询,属于过滤条件,不参与算分,放到must_not中;
  • 周围10km范围内,用geo_distance查询,属于过滤条件,不参与算分,放到filter中。

最终的DSL语句如下:

# 布尔查询
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}}}}}
}

7 搜索结果处理

7.1 排序

ES默认是根据相关度算分(_score)来倒序排序的,但是也支持自定义方式对搜索结果进行排序。

支持排序的字段类型有:keyword类型、数值类型、地理坐标类型、日期类型等。

7.1.1 普通字段排序

keyword、数值、日期类型排序的语法基本一致。

例如有以下需求:各酒店按照用户评分(score)降序排序,评分相同再按照价格(price)升序排序。其DSL语句如下:

# 普通字段排序
GET /hotel/_search
{"query": {"match_all": {              //查询条件,这里指匹配全部}},"sort": [{"score": "desc"         //按照用户评分(score)降序排序},{"price": "asc"          //按照价格(price)升序排序}]
}

可见,排序条件是一个数组,也就是说可以同时写多个排序条件,此时会按照声明的顺序进行排序,当第1个排序条件相等时,则再按照第2个排序条件进行排序,以此类推。

7.1.2 地理坐标排序

地理坐标排序需要指定一个坐标坐标作为目标点,然后计算文档中指定字段(必须是geo_point类型)的坐标到目标点的距离,根据距离进行排序。

例如,有以下需求:实现对酒店按照到当前位置坐标的距离升序排序。其DSL语句如下:

# 地理坐标排序
GET /hotel/_search
{"query": {"match_all": {}},"sort": [{"_geo_distance": {"location": {               //指定的geo_point类型的字段"lat": 31.034661,       //当前位置纬度"lon": 121.612282       //当前位置经度},"order": "asc",             //asc、desc"unit": "km"                //距离单位}}]
}

本节完,更多内容请查阅分类专栏:微服务学习笔记

感兴趣的读者还可以查阅我的另外几个专栏:

  • SpringBoot源码解读与原理分析
  • MyBatis3源码深度解析
  • Redis从入门到精通
  • MyBatisPlus详解
  • SpringCloud学习笔记

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Git 下载安装使用基本教程

一、下载 Git&#xff0c;并安装 Git for Windows&#xff0c; 无脑安装。安装完&#xff0c;鼠标右键&#xff0c;会看到这两个东西。 二、Gitee操作 新建仓库 初始化 readme 文件 点击克隆 复制地址 右键 git clone 第一次会需要你输入账号密码 输入后拉取成功。 把想要上传…

【安全生产】叉车安全带报警器有哪些特点?

叉车安全带报警器是用于防止在叉车发生猛烈碰撞或紧急制动时&#xff0c;司机不与方向盘、挡风玻璃等发生二次碰撞或抛出车外&#xff0c;从而造成的严重伤害的一种叉车安全装置、配件。 很多司机在开叉车时经常有不系安全带的习惯&#xff0c;有很多不负责任的人会认为&#…

PHP一键发起灵活定制多功能投票小程序系统源码

​一键发起&#xff0c;灵活定制 —— 多功能投票小程序 &#x1f680;【开篇&#xff1a;告别繁琐&#xff0c;投票新体验】&#x1f680; 还在为组织投票活动而头疼不已吗&#xff1f;繁琐的流程、有限的选项、难以统计的结果...这些都将成为过去式&#xff01;今天&#x…

MyPrint打印设计器(六)svg篇-直线

svg-二阶贝塞尔曲线 介绍一款强大的svg操作库&#xff0c;能够通过简单的代码&#xff0c;实现svg绘制与操纵&#xff0c;实现拖拽等功能 代码仓库 在线体验 代码仓库&#xff1a;github 代码仓库&#xff1a;gitee 实战项目&#xff1a;MyPrint 操作简单&#xff0c;组件丰富…

notepad++将换行替换成空

将多行里的换行置为一行&#xff0c;例如将下面的6行置为3行 crrlH打开替换框&#xff0c; 替换目标为【,\r\n】&#xff0c;替换成空&#xff0c;勾选循环查找和 正则表达式&#xff0c;全部替换即可。 替换后的效果

【AI】Pytorch_模型构建

建议点赞收藏关注&#xff01;持续更新至pytorch大部分内容更完。 本文已达到10w字&#xff0c;故按模块拆开&#xff0c;详见目录导航。 整体框架如下 数据及预处理 模型及其构建 损失函数及优化器 本节目录 模型线性回归逻辑回归LeNetAlexNet 构建模块组织复杂网络初始化网络…

中国各地级市的海拔标准差

海拔标准差是衡量地理测量准确性的重要指标&#xff0c;它通过计算特定地点的海拔测量值与平均海拔之间的偏差来评估数据的可靠性。较小的标准差意味着测量结果较为一致&#xff0c;而较大的标准差则可能指出数据的波动性或测量误差。 计算方法 海拔标准差的计算遵循以下公式…

【pycharm-乱码】简单记录一下都有哪些涉及编码

控制台 路径&#xff1a;setting-》general-》console setting-》editor-》file encodings 路径&#xff1a;setting-》editor->file and code templates #!/user/bin/env python3 # -*- coding: utf-8 -*-setting->tools->ssh terminal

新款14 英寸和16英寸MacBook Pro开始组装生产

据 DigiTimes 报道&#xff0c;苹果的供应链已于 8 月开始批量生产搭载 M4 Pro 和 M4 Max 芯片的下一代 14 英寸和 16 英寸 MacBook Pro 机型。这意味着笔记本电脑的组装工作很可能已经开始。 此信息与显示行业分析师 Ross Young 的说法相符&#xff0c;他声称下一代 14 英寸和…

Edge资源占用优化:调整浏览器设置与关闭自动更新检查

最近&#xff0c;作者在学习过程中&#xff0c;打开任务管理器的时候注意到&#xff0c;即使没有打开浏览器&#xff0c;edge依然有着内存占用较高的情况&#xff1a; 于是就在网上收集了一些后台调优的方法&#xff0c;如果各位朋友有更多优化浏览器资源占用的方法&#xff0c…

智能优化特征选择|基于鲸鱼WOA优化算法实现的特征选择研究Matlab程序(KNN分类器)

智能优化特征选择|基于鲸鱼WOA优化算法实现的特征选择研究Matlab程序&#xff08;KNN分类器&#xff09; 文章目录 一、基本原理原理流程举个例子总结 二、实验结果三、核心代码四、代码获取五、总结 智能优化特征选择|基于鲸鱼WOA优化算法实现的特征选择研究Matlab程序&#x…

【Linux系统】线程的同步 生产消费模型

同步 同步概念 同步&#xff1a;在保证数据安全的前提下&#xff0c;让线程能够按照某种特定的顺序访问临界资源&#xff0c;从而有效避免饥饿问题&#xff0c;叫做同步 竞态条件&#xff1a;因为时序问题&#xff0c;而导致程序异常&#xff0c;我们称之为竞态条件。在线程场…

[OpenCV] 数字图像处理 C++ 学习——13Canny边缘检测 附完整代码

文章目录 前言1.理论基础(1)高斯模糊平滑图像(GaussianBlur)(2)计算图像梯度(Sobel/Scharr)(3)非极大值抑制 (Non-maximum Suppression)(4)双阈值检测 (Double Threshold)(5)边缘跟踪&#xff08;通过滞后处理&#xff09; 2.代码实现3.完整代码 前言 Canny 边缘检测(高斯滤波…

django学习入门系列之第十点《django中数据库操作--创建与删除表》

文章目录 django创建与删除表开始创建表创建指令新增表删除表删除列新增列修改报错提示语言总结 往期回顾 django创建与删除表 删除表 创建表 修改表 操作目录 开始创建表 class text_into(models.Model):name models.CharField(max_length32)password models.CharField…

Electron快速上手

什么是Electron 一款应用广泛的跨平台的桌面应用开发框架。Electron的本质是结合了 Chromium 与Node.js。使用HTML、CSS、JS 等Web技术构建桌面应用程序。 .vue,.tsx,.less,.ts也可以使用 Electron 流程模型 主进程是纯node环境&#xff0c;可以访问__dirname,fs模块等&#…

DDD设计方法-3-仓储,封装持久化数据

前情提要&#xff1a;一共包含 如下六篇文章&#xff08;篇幅精简&#xff0c;快速入门&#xff09; 1、初识DDD 2、聚合、实体、值对象 3、仓储&#xff0c;封装持久化数据 4、端口和适配器 5、领域事件 6、领域服务&#xff0c;实现约定 DDD设计方法-3-仓储&#xff0c;封装…

绿联充电宝怎么样?深度测评西圣、绿联、倍思磁吸充电宝!

在如今这个电子设备不离手的时代&#xff0c;充电宝成为了我们生活中不可或缺的伙伴。而磁吸充电宝以其便捷的使用方式和时尚的外观&#xff0c;更是受到了众多消费者的青睐&#xff0c;今天&#xff0c;我们将对西圣、绿联、倍思这三个品牌的磁吸充电宝进行深度测评&#xff0…

Three之材质Material

本文目录 前言一、基础材质1.1 特点及属性1.2 代码1.3 效果 二、标准材质2.1 特点及属性2.2 代码及效果 三、深度材质四、法向材质五、朗伯材质六、Phong式材质七、粒子材质八、 着色器材质九、其他材质 前言 Three.js中的材质&#xff08;Material&#xff09;是独立于物体顶点…

Anthropic Claude Artifacts,克劳德聊天机器人如何简化代码编程

最近有一位8岁的小男孩&#xff0c;没有任何编程经验&#xff0c;却成功创建了一个网页游戏。他利用了Claude AI和Cursor来生成代码&#xff0c;这充分展示了人工智能在简化编程和创作过程中的巨大潜力。前几天还能看见一个8岁的女孩用生成式人工智能Cursor ai工具可以搭建出一…

一款基于Vue的低代码可视化表单设计器工具,6K star的可视化表单设计器工具,轻松搞定表单,支持多端适配(附源码)

前言 随着Web应用的日益复杂化&#xff0c;表单的设计与开发成为了许多项目中不可或缺的一环。然而&#xff0c;在实际cao作过程中&#xff0c;表单设计往往面临着重复工作量大、效率低下等问题。那么&#xff0c;是否有一款工具能够简化这一过程&#xff0c;提高开发者的效率…