实用篇-ES-DSL查询文档

数据的存储不是目的,我们希望从海量的酒店数据中检索出需要的信息,这就是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>" // 用来标记高亮字段的后置标签
      }
    }
  }
}

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

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

相关文章

vite vue3配置eslint和prettier以及sass

准备 教程 安装eslint 官网 vue-eslint ts-eslint 安装eslint yarn add eslint -D生成配置文件 npx eslint --init安装其他插件 yarn add -D eslint-plugin-import eslint-plugin-vue eslint-plugin-node eslint-plugin-prettier eslint-config-prettier eslint-plugin…

【数据结构】图的存储结构及实现(邻接表和十字链表)

一.邻接矩阵的空间复杂度 假设图G有n个顶点e条边&#xff0c;则存储该图需要O&#xff08;n^2) 不适用稀疏图的存储 二.邻接表 1.邻接表的存储思想&#xff1a; 对于图的每个顶点vi&#xff0c;将所有邻接于vi的顶点链成一个单链表&#xff0c;称为顶点vi的边表&#xff08…

C/C++ 运用VMI接口查询系统信息

Windows Management Instrumentation&#xff08;WMI&#xff09;是一种用于管理和监视Windows操作系统的框架。它为开发人员、系统管理员和自动化工具提供了一种标准的接口&#xff0c;通过这个接口&#xff0c;可以获取有关计算机系统硬件、操作系统和应用程序的信息&#xf…

PS学习笔记——新建文档/修改文档

文章目录 新建文档文档属性像素/分辨率颜色模式背景内容高级选项存储预设 修改文档 新建文档 方法一&#xff1a;ctrlN快捷键可直接打开新建文档界面 方法二&#xff1a;点击菜单栏中 文件->新建&#xff0c;即可打开新建文档界面 文档参数可按需调节(标题可以提前设定或者…

face_recognition:高准确率、简单易用的人脸识别库 | 开源日报 No.79

ageitgey/face_recognition Stars: 49.8k License: MIT 这个项目是一个使用 Python 编写的人脸识别库&#xff0c;可以从图片中识别和操作人脸。它基于 dlib 开发&#xff0c;并采用深度学习技术构建了最先进的人脸识别模型&#xff0c;在 Labeled Faces in the Wild 数据集上…

Redis(消息队列Stream)

Stream是一个轻量级的消息队列。 Redis中Stream的作用是提供一种高效的消息传递机制&#xff0c;允许多个消费者并行地消费消息&#xff0c;并且不会重复消费已经处理过的消息。它可以用于实现分布式任务队列、日志收集、实时数据处理等场景。Redis中的Stream支持多个消费者组…

Python数据分析实战① Python实现数据可视化

文章目录 一、数据可视化介绍二、matplotlib和pandas画图1.matplotlib简介和简单使用2.matplotlib常见作图类型3.使用pandas画图4.pandas中绘图与matplotlib结合使用 三、订单数据分析展示四、Titanic灾难数据分析显示 一、数据可视化介绍 数据可视化是指将数据放在可视环境中…

6.2 List和Set接口

1. List接口 List接口继承自Collection接口&#xff0c;List接口实例中允许存储重复的元素&#xff0c;所有的元素以线性方式进行存储。在程序中可以通过索引访问List接口实例中存储的元素。另外&#xff0c;List接口实例中存储的元素是有序的&#xff0c;即元素的存入顺序和取…

【Linux网络编程】高级I/O

目录 五种I/O模型 阻塞和非阻塞 非阻塞I/O I/O多路复用之Select、Poll、与Epoll 本文目的是深入浅出理解高级I/O相关的知识&#xff0c;结尾附上代码加深理解相关知识。 五种I/O模型 1.阻塞I/O&#xff1a;在内核将数据准备好之前&#xff0c;系统调用会一直等待。所有的套…

【踩坑笔记】国科GK7202V300芯片开发常见问题解决办法

国科Linux芯片开发常见问题&解决办法 0.读前须知 不管什么时候&#xff0c;下载程序还是啥&#xff0c;一定要检查路径&#xff01;&#xff01;&#xff01;别问我为什么&#xff0c;呜呜呜~ tips&#xff1a;该芯片是仿造海思的产品&#xff0c;所以&#xff0c;有些不…

cp: can‘t stat ‘/usr/share/zoneinfo/Asia/Shanghai‘: No such file or directory

目录 问题描述问题分析解决方案容器时区验证 问题描述 使用下面的 Dockerfile 为 youlai-boot 项目制作镜像设置容器时区报错。 # 基础镜像 FROM openjdk:17-jdk-alpine # 时区修改 RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \&& echo Asia/Sha…

【每周一测】Java阶段三阶段考试

目录 1、SpringBoot在整合RabbitMQ时需要导入的包是 2、下列关于RabbitMQ的confirm消息确认机制解释说明正确的是 3、关于SpringBoot的配置文件&#xff0c;以下说法正确的是&#xff08;&#xff09; 4、变量命名规范说法正确的是? 5、哪个关键字可以对对象加互斥锁&…

计算机视觉的应用18-一键抠图人像与更换背景的项目应用,可扩展批量抠图与背景替换

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下计算机视觉的应用18-一键抠图人像与更换背景的项目应用&#xff0c;可扩展批量抠图与背景替换。该项目能够让你轻松地处理和编辑图片。这个项目的核心功能是一键抠图和更换背景。这个项目能够自动识别图片中的主体&…

医院绩效考核系统源码 医院绩效考核系统方案

医院绩效考核系统源码 医院绩效考核系统是现代医院管理的重要方法和科学的管理工具。良好的绩效管理&#xff0c;有助于带动全院职工的工作积极性&#xff0c;有助于提高工作效率、提高医疗质量、改善服务水平、降低运营成本&#xff0c;全面提升医院的精细化管理水平。 医院绩…

Flask学习一:概述

搭建项目 安装框架 pip install Flask第一个程序 from flask import Flaskapp Flask(__name__)app.route(/) def hello_world():return "Hello World"if __name__ __main__:app.run()怎么说呢&#xff0c;感觉还不错的样子。 调试模式 if __name__ __main__:a…

后端老项目迁移方法

老项目迁移方法 需求&#xff1a; 因某个模块MySQL表结构、表关系 错乱复杂&#xff0c;而且其他模块的代码也在操作这个模块的数据库 耦合严重 导致Web工程代码紊乱、不易理解、性能低下&#xff0c; 故在 系统由A JavaWeb工程迁移至B工程 时&#xff0c;重构MySQL表结构、表…

VS中修改解决方案名称和项目名称

如何修改visual studio2019中的项目名 - 知乎 (zhihu.com) 查了很多&#xff0c;还是这个可行。虽然文中说不是最简单的&#xff0c;但在所查找资料中是可行且最简单的。 要点主要是&#xff1a; 1、比如我们复制一个解决方案&#xff0c;最好是带代码哈&#xff0c;也就是添…

ToolJet:开源低代码框架,轻松构建复杂可响应界面 | 开源日报 No.78

ToolJet/ToolJet Stars: 25.0k License: AGPL-3.0 ToolJet 是一个开源的低代码框架&#xff0c;可以通过最小化工程投入来构建和部署内部工具。ToolJet 的拖放式前端构建器允许您在几分钟内创建复杂、响应式的前端界面。此外&#xff0c;您还可以集成各种数据源&#xff0c;包…

java使用 TCP 的 Socket API 实现客户端服务器通信

一&#xff1a;什么是 Socket(套接字) Socket 套接字是由系统提供于网络通信的技术, 是基于 TCP/IP 协议的网络通信的基本操作&#xff0c;要进行网络通信, 需要有一个 socket 对象, 一个 socket 对象对应着一个 socket 文件, 这个文件在 网卡上而不是硬盘上, 所以有了 sokcet…

互联网医院牌照|智慧医疗离不开牌照办理

互联网医院牌照是由卫生健康行政部门颁布的&#xff0c;所有材料审核通过后&#xff0c;相关部门授予《医疗机构执业许可证》&#xff0c;取得牌照后才有开展互联网诊疗活动的资质&#xff0c;但开展线上问诊也需要向发证机关提出申请&#xff0c;下面小编就给大家讲解下互联网…