实用篇-ES-DSL查询文档

news2024/11/28 16:26:18

数据的存储不是目的,我们希望从海量的酒店数据中检索出需要的信息,这就是ES的搜索功能

官方文档: https://elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html#query-dsl。DSL是用来查询文档的

Elasticsearch提供了基于JSON的DSL来定义查询,简单说就是用json来描述查询条件,然后发送给es服务,最后es服务基于查询条件,把结果返回给我们

常见的查询类型包括如下:

1、查询所有: 查询出所有数据,一般在测试的时候使用

match_all

2、全文检索查询: 利用分词器对用户输入内容进行分词,然后去倒排索引库中匹配

match_query
multi_match_query

3、精确查询: 根据精确的词条值去查找数据,一般是查找keyword、数值、日期、boolean等类型的字段。这些字段是不需要分词的,但是依旧会建立倒排索引,把字段的整体内容作为一个词条,并存入倒排索引。在查找的时候,也就不需要分词,直接把搜索的内容去跟倒排索引匹配即可

ids,表示根据id,进行精确匹配

range,表示根据数值范围,进行精确匹配

term,表示根据数据的值,进行精确匹配

4、地理查询: 根据经纬度查询

geo_distance
geo_bounding_box

5、复合查询: 复合查询可将上述各种查询条件组合一起,合并查询条件

bool,利用逻辑运算把其它查询条件组合起来
function_score,用于控制相关度算分,算分会影响性能

一、DSL查询语法

GET /hotel/_search
{
  "query": {
    "match_all": {}
  }
}

存在一个问题,我们明明查询的是所有文档,查询结果也显示查询出所有的文档了,为什么上图右侧,鼠标往下拉,最多才只有10条文档数据呢

原因: 受默认的分页条件限制,后面学习的时候,会进行解决

二、全文检索查询

首先保证你已经做好了 '实用篇-ES-环境搭建' ,创建了名为hotel的索引库,导入了批量文档。然后开始下面的操作

全文检索查询,分为下面两种,会对用户输入内容进行分词之后,再进行匹配。也就是利用分词器对用户输入内容进行分词,然后去倒排索引库中匹配

match_query
multi_match_query

【第一种全文检索查询】

match查询(也就是match_query查询): 全文检索查询的一种,会对用户输入的内容进行分词,然后去倒排索引库检索

GET /索引库名/_search
{
  "query": {
    "match": {
      "字段名": "TEXT"
    }
  }
}

具体操作如下,为了让大家知道hotel索引库有哪些字段,我把当初建立gghotel索引库的类先放出来

package cn.itcast.hotel.constants;

public class HotelConstants {
     public static final String MAPPING_TEMPLATE = "{\n" +
             "  \"mappings\": {\n" +
             "    \"properties\": {\n" +
             "      \"id\":{\n" +
             "        \"type\": \"keyword\"\n" +
             "      },\n" +
             "      \"name\":{\n" +
             "        \"type\": \"text\",\n" +
             "        \"analyzer\": \"ik_max_word\",\n" +
             "        \"copy_to\": \"all\"\n" +
             "      },\n" +
             "      \"address\":{\n" +
             "        \"type\": \"keyword\",\n" +
             "        \"index\":false\n" +
             "      },\n" +
             "      \"price\":{\n" +
             "        \"type\": \"integer\"\n" +
             "      },\n" +
             "      \"score\":{\n" +
             "        \"type\": \"integer\"\n" +
             "      },\n" +
             "      \"brand\":{\n" +
             "        \"type\": \"keyword\",\n" +
             "        \"copy_to\": \"all\"\n" +
             "      },\n" +
             "       \"city\":{\n" +
             "        \"type\": \"keyword\"\n" +
             "      },\n" +
             "       \"starName\":{\n" +
             "        \"type\": \"keyword\"\n" +
             "      },\n" +
             "       \"business\":{\n" +
             "        \"type\": \"keyword\",\n" +
             "        \"copy_to\": \"all\"\n" +
             "      },\n" +
             "       \"location\":{\n" +
             "        \"type\": \"geo_point\"\n" +
             "      },\n" +
             "      \"pic\":{\n" +
             "        \"type\":\"keyword\",\n" +
             "        \"index\": false\n" +
             "      },\n" +
             "      \"all\":{\n" +
             "        \"type\": \"text\",\n" +
             "        \"analyzer\": \"ik_max_word\"\n" +
             "      }\n" +
             "    }\n" +
             "  }\n" +
             "}";
}

注意: 我要解释一下,上面有个字段叫all,那个字段是当时自定义的,不清楚的话可回去看 '实用篇-ES-RestClient操作' 的 'hotel数据结构分析'。

all的作用如下图,相当于一个大的字段,里面存放了几个小字段,优点是我们可以在这个大的字段里面搜索到多个小字段的信息

然后,我们就正式开始全文检索查询,输入如下。注意all换成其它字段也没事,例如换成name字段。正常来说,我们检索name字段,就只在name字段检索匹配的分词文档,但是在all字段里面检索时,也会检索到name、brand、business字段,原因如上面那个图的copy_to属性

GET /hotel/_search
{
 "query": {
  "match": {
    "all": "外滩"
  }
 }
}

//或者如下
# 第一种全文检索查询 match。查询name字段中包含'酒店'的文档
GET /hotel/_search
{
 "query": {
  "match": {
    "name": "酒店"
  }
 }
}

【第二种全文检索查询】

multi_match(也就是multi_match_query查询): 与match查询类似,只不过允许同时查询多个字段

GET /索引库名/_search
{
  "query": {
    "multi_match": {
      "query": "TEXT",
      "字段名": ["FIELD1", " FIELD12"]
    }
  }
}
# 第二种全文检索查询 multi_match。查询business、brand、name字段中包含'如家'的文档,满足一个字段即可
GET /hotel/_search
{
 "query": {
  "multi_match": {
    "query": "如家",
    "fields":["business","brand","name"]
  }
 }
}

三、精确查询

term: 根据词条的精确值查询,强调精确匹配

range: 根据值的范围查询,例如金额、时间

【第一种精确查询 term】

具体操作如下

查询city为杭州

GET /hotel/_search
{
"query":{
  "term":{
    "city":{
      "value":"杭州"
    }
  }
 }
}

【第二种精确查询 range】

GET /hotel/_search
{
  "query": {
    "range": {
      "price": {
        "gte": 10,
        "lte": 20
      }
    }
  }
}

四、地理查询

根据经纬度查询。常见的使用场景包括: 查询附近酒店、附近出租车、搜索附近的人。使用方式有很多种,介绍如下,这种最常用

geo_distance: 查询到指定中心点,以该点为圆心,distance为半径的圆,符合要求的所有文档

GET /索引库名/_search
{
  "query": {
    "geo_distance": {
      "distance": "15km",
      "字段名": "31.21,121.5"
    }
  }
}

具体操作如下

输入如下DSL语句

GET /hotel/_search
{
  "query": {
    "geo_distance": {
      "distance": "15km",
      "location": "31.21,121.5"
    }
  }
}

五、相关性算分

上面学的全文检索查询、精确查询、地理查询,这三种查询在es当中都称为简单查询,下面我们将学习复合查询。复合查询可以其它简单查询组合起来,实现更复杂的搜索逻辑,其中就有 '算分函数查询' 如下

首先保证你已经做好了 '实用篇-ES-环境搭建' ,创建了名为hotel的索引库,导入了批量文档。然后开始下面的操作

算分函数查询(function score): 可以控制文档相关性算分、控制文档排名。例如搜索'外滩' 和 '如家' 词条时,某个文档要是都能匹配这两个词条,那么在所有被搜索出来的文档当中,这个文档的位置就最靠前,简单说就是越匹配就排名越靠前

六、函数算分查询

上面只是简单演了相关性打分中的函数算分查询,文档与搜索关键字的相关度越高,打分就越高,排名就越靠前。不过,有的时候,我们希望人为地去控制控制文档的排名,例如某些文档我们就希望排名靠前一点,算分高一点,此时就需要使用函数算分查询,下面就来学习 '函数算分查询'

首先保证你已经做好了 '实用篇-ES-环境搭建' ,创建了名为gghotel的索引库,导入了批量文档。然后开始下面的操作

使用 ’函数算分查询(function score query)’,可以在原始的相关性算分的基础上加以修改,得到一个想要的算分,从而去影响文档的排名,语法如下

GET /索引库名/_search
{
  "query": {
    "function_score": {
      "query": { "match": {"字段": "词条"} },
      "functions": [
        {
          "filter": {"term": {"指定字段": "值"}},
          "算分函数": 函数结果
        }
      ],
      "boost_mode": "加权模式"
    }
  }
}

function score需要考虑的三要素

1. 哪些文档需要算分加权

2. 算分函数是什么

3. 加权模式是什么

下面我们实现一个案例:给如家这个品牌的酒店排名靠前一些

考虑三要素

1. 哪些文档需要算分加权     brand为如家的酒店

2. 算分函数是什么               weigh

3. 加权模式是什么                相加/相乘都可

输入如下DSL语句,表示在 '如家' 这个品牌中,字段为'北京'的酒店排名靠前一些

GET /hotel/_search
{
  "query": {
    "function_score": {
      "query": {"match": {
        "brand": "如家"
      }},
      "functions": [
        {
          "filter": {
            "term": {
              "city": "北京"
            }
          },
          "weight": 2
        }
      ],
      "boost_mode": "sum"
    }
  }
}

七、布尔查询

这是第二种复合查询

布尔查询不会去修改算分,而是把多个查询语句组合成一起,形成新查询,这些被组合的查询语句,被称为子查询。子查询的组合方式有如下四种

1、must:必须匹配每个子查询,类似"与"

2、should:选择性匹配子查询,类似"或"

3、must_not:必须不匹配,不参与算分,类似"非"

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

首先保证你已经做好了 '实用篇-ES-环境搭建' ,创建了名为gghotel的索引库,导入了批量文档。然后开始下面的操作

输入如下DSL语句,表示搜索名字包含'如家',价格不高于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",
            "xxlocation": {
              "lat": 31.21,
              "lon": 121.5
            }
          }
        }
      ]
    }
  }
}

八、搜索结果处理

lasticsearch(称为es)支持对搜索的结果,进行排序,默认是根据 '相关度' 算分,也就是score值,根据score值进行排序。

可以排序的字段类型有: keyword类型、数值类型、地理坐标类型、日期类型

首先保证你已经做好了 '实用篇-ES-环境搭建' ,创建了名为gghotel的索引库,导入了批量文档。然后开始下面的操作

1. 排序

输入如下DSL语句,表示对所有的文档,根据评分(score)进行降序排序,如果评分相同就根据价格(price)升序排序

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

2. 分页

elasticsearch(称为es)默认情况下只返回前10 条数据。而如果要查询更多数据就需要修改分页参数,分页参数包括from和size,语法如下

GET /索引库名/_search
{
  "query": {
    "要查询的字段": {}
  },
  "from": 要查第几页, // 分页开始的位置,默认为0
  "size": 每页显示多少条文档, // 期望获取的文档总数
  "sort": [ //表示排序
    {"price": "排序方式"}
  ]
}

输入如下DSL语句,表示对所有的文档,根据价格(price)进行升序排序,每次分页显示20条数据,看的是第六页

size默认是10,表示一页显示多少条文档。from默认是0,表示你要看的是第一页

GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "price": {
        "order": "asc"
      }
    }
  ],
  "from": 5,
  "size": 20
}

3. 搜索结果处理-高亮

高亮: 就是在搜索结果中把搜索关键字突出显示。高亮显示的原理如下

1、将搜索结果中的关键字用标签标记出来

2、在页面中给标签添加css样式

首先保证你已经做好了 '实用篇-ES-环境搭建' ,创建了名为gghotel的索引库,导入了批量文档。然后开始下面的操作

语法

GET /索引库名/_search
{
  "query": {
    "match": { //match表示带关键字的查询
      "字段": "TEXT"
    }
  },
  "highlight": {
    "fields": {
      "字段名": {
        "require_field_match": "false",//默认是true,表示 '字段' 要和 '字段名' 要一致。如果我们写的是不一致的话,就需要修改为false
        "pre_tags": "<em>",  // 用来标记高亮字段的前置标签,es会帮我们把标签加在关键字上。默认是<em>
        "post_tags": "</em>" // 用来标记高亮字段的后置标签,es会帮我们把标签加在关键字上。默认是</em>
      }
    }
  }
}

 总结

GET /索引库名/_search
{
  "query": {
    "match": {
      "字段名": "如家"
    }
  },
  "from": 0, // 分页开始的位置
  "size": 20, // 期望获取的文档总数
  "sort": [ 
    {  "price": "asc" }, // 普通排序
    {
      "_geo_distance" : { // 距离排序
          "location" : "31.040699,121.618075", 
          "order" : "asc",
          "unit" : "km"
      }
    }
  ],
  "highlight": {
    "fields": { // 高亮字段
      "字段名": {
        "pre_tags": "<em>",  // 用来标记高亮字段的前置标签
        "post_tags": "</em>" // 用来标记高亮字段的后置标签
      }
    }
  }
}

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

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

相关文章

SaaS与PaaS平台的区别

目录 一、前言 二、SaaS化与PaaS化平台的区别 三、PaaS化的低代码平台更胜一筹 PaaS优势&#xff1a; 支持PaaS服务的低代码平台 1.私有化部署&#xff0c;为数据安全保驾护航 2.业内领先技术&#xff0c;为开发强势赋能 3.超强集成能力&#xff0c;系统对接无忧 4.源代码交付&…

openEuler 系统操作 Docker Compose 容器化部署 Redis Cluster 集群的节点添加、删除和可视化监控

容器化部署 Redis Cluster 集群的节点添加、删除和可视化监控 Redis Cluster 集群回顾openEuler 系统查看端口是否被占用Redis Cluster 验证Redis CLI 客户端命令验证Redis GUI 工具验证宿主机安装 RedisInsightDocker 容器化部署 RedisInsight 添加集群节点启动 Reids 扩容服务…

接口自动化测试面试题

前言 前面总结了一篇关于接口测试的常规面试题&#xff0c;现在接口自动化测试用的比较多&#xff0c;也是被很多公司看好。那么想做接口自动化测试需要具备哪些能力呢&#xff1f; 也就是面试的过程中&#xff0c;面试官会考哪些问题&#xff0c;知道你是不是真的做过接口自动…

【Spring】 Spring中的IoC(控制反转)

以往在定义业务层实现时&#xff0c;在指定具体地Dao时候需要具体地定义出其实现&#xff1a; public class BookServiceImpl implements BookService{private BookDao bookDao new BookDaoImpl();public void save(){bookDao.save()} }public class BookDaoImpl implements …

python连接redis库

在自动化过程中&#xff0c;如果需要动态获取某个数据时&#xff0c;需要连接redis数据库。下面来详细介绍下如何操作。 redis这个库是python自带的&#xff0c;直接import导入即可,如下; import redis 1. redis 地址和端口&#xff0c;端口一般都是默认的6379,只需要换下地…

第08章 面向对象编程(高级)

一 关键字&#xff1a;static class Circle{private double radius;public Circle(double radius){this.radiusradius;}public double findArea(){return Math.PI*radius*radius;} }创建两个Circle对象&#xff1a; Circle c1new Circle(2.0); //c1.radius2.0 Circle c2new C…

python如何批量创建文件与文件夹

目录 一、引言 二、批量创建文件 1、使用os模块 2、使用pathlib模块 三、批量创建文件夹 1、使用os模块 2、使用pathlib模块 四、注意事项 五、总结与展望 一、引言 在Python中&#xff0c;我们经常需要创建文件和文件夹来存储和管理数据。批量创建文件和文件夹可以大…

实用技巧:在C和cURL中设置代理服务器爬取www.ifeng.com视频

概述&#xff1a; 网络爬虫技术作为一种自动获取互联网数据的方法&#xff0c;在搜索引擎、数据分析、网站监测等领域发挥着重要作用。然而&#xff0c;面对反爬虫机制、网络阻塞、IP封禁等挑战&#xff0c;设置代理服务器成为解决方案之一。代理服务器能够隐藏爬虫的真实IP地…

Everything——检索神兵

相信在日常生活工作中&#xff0c;大家肯定会有这样的困惑&#xff1a;由于一时疏忽&#xff0c;自己下载或编写的文件保存的路径丢失&#xff0c;想再次在茫茫内存中找到会很麻烦。今天学长将带来一款软件——Everything&#xff0c;其拥有强大的搜索功能&#xff0c;可以帮助…

UI游戏设计模板大放送:7种别具匠心的创意!

随着游戏产业的快速发展&#xff0c;UI游戏设计已经成为一个热门的设计行业&#xff0c;但与之前的设计相比&#xff0c;UI游戏设计还是比较特殊的&#xff0c;主要体现在UI游戏设计难度大&#xff0c;需要大量的手绘内容和对游戏玩法的理解上。这些门槛需要大量的时间去学习&a…

【Git学习一】初始化仓库git init的使用和提交git add与git commit的使用

&#x1f601; 作者简介&#xff1a;一名大四的学生&#xff0c;致力学习前端开发技术 ⭐️个人主页&#xff1a;夜宵饽饽的主页 ❔ 系列专栏&#xff1a;Git等软件工具技术的使用 &#x1f450;学习格言&#xff1a;成功不是终点&#xff0c;失败也并非末日&#xff0c;最重要…

C++初阶-内存管理

内存管理 一、C/C内存分布二、C语言中动态内存管理方式&#xff1a;malloc/calloc/realloc/free三、C内存管理方式new/delete操作内置类型new和delete操作自定义类型 四、operator new与operator delete函数operator new与operator delete函数 五、new和delete的实现原理内置类…

Abaqus2023新功能:分析技术

隐式耦合的松弛和加速器方法 产品&#xff1a;Abaqus/Standard SIMULIA协同仿真引擎现在支持Aitkens松弛方法以及Anderson和Broyden加速器方法&#xff0c;为强耦合物理场提供稳健且省时高效的解决方案。此功能在 2022 FD04 &#xff08;FP.2232&#xff09;版本中首次提供。…

文件包含_常见文件包含情况

文件包含系列 相关函数 分类 实践 包含实现的场景

解决编译时提示“没有那个文件或目录 #include <pcap.h>”的问题

解决编译时提示“没有那个文件或目录 #include 当你在编译代码时遇到“没有那个文件或目录 #include <pcap.h>”的错误提示&#xff0c;这通常意味着编译器在你的系统路径中找不到 pcap.h 头文件。pcap.h 是网络流量捕获库 pcap 的头文件&#xff0c;用于在 C/C 程序中捕…

07 robotframework JS和RFS值传递

1、JS的值传给RFS变量 示例1&#xff1a; ${bb} Execute Javascript function rand ( n ){return ( Math.floor ( Math.random ( ) * n 1 ) );};var aa rand(100);return aa; sleep ${bb}ms 示例2&#xff1a; var a [];$("iframe&quo…

网站提示Internal Server Error的原因和解决方法分享

解决方法 登陆FTP或文件管理器,检查站点目录文件权限设置,将文件夹权限设置为755,单个文件权限设置为644。 这样设置644后,问题就可以解决,同时也不会影响网站的所需要的写入权限,满足网站正常运行。如果你的站点中有很多权限都要需要设置,为了提高效率。 应用导致分析…

巴菲特再度出手,清仓7家公司股票

KlipC报道&#xff1a;最新数据显示&#xff0c;伯克希尔第三季度总共清仓了7家公司的股份&#xff0c;其中包括动视暴雪、通用汽车、化工巨头塞拉尼斯、亿滋国际、强生、宝洁和联合包裹。 KlipC的合伙人Andi D表示&#xff1a;“此前最新的监管文件显示&#xff0c;伯克希尔哈…

QtiPlot for Mac v1.1.3(科学数据分析工具)

QtiPlot是一款跨平台科学绘图软件&#xff0c;它可以在Windows、Linux和Mac OS X等多个平台上运行。QtiPlot具有强大的数据分析和可视化功能&#xff0c;被广泛应用于学术界和工业界的数据处理和图形制作。 QtiPlot支持多种语言&#xff0c;包括但不限于英语、中文等&#xff…

微信小程序如何跳转到微信公众号文章,小程序如何关联公众号或订阅号

微信小程序如何跳转到微信公众号文章&#xff0c;小程序如何关联公众号或订阅号 前置条件 公众号最高管理权限&#xff08;或能与最高权限管理者配合操作&#xff09;小程序开发权限或最高管理权限 小程序方面 根据官方资料描述&#xff0c;小程序中展示微信公众号中的文章…