CodeAshen's blog CodeAshen's blog
首页
  • Spring Framework

    • 《剖析Spring5核心原理》
    • 《Spring源码轻松学》
  • Spring Boot

    • Spring Boot 2.0深度实践
  • Spring Cloud

    • Spring Cloud
    • Spring Cloud Alibaba
  • RabbitMQ
  • RocketMQ
  • Kafka
  • MySQL8.0详解
  • Redis从入门到高可用
  • Elastic Stack
  • 操作系统
  • 计算机网络
  • 数据结构与算法
  • 云原生
  • Devops
  • 前端
  • 实用工具
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
  • Reference
GitHub (opens new window)

CodeAshen

后端界的小学生
首页
  • Spring Framework

    • 《剖析Spring5核心原理》
    • 《Spring源码轻松学》
  • Spring Boot

    • Spring Boot 2.0深度实践
  • Spring Cloud

    • Spring Cloud
    • Spring Cloud Alibaba
  • RabbitMQ
  • RocketMQ
  • Kafka
  • MySQL8.0详解
  • Redis从入门到高可用
  • Elastic Stack
  • 操作系统
  • 计算机网络
  • 数据结构与算法
  • 云原生
  • Devops
  • 前端
  • 实用工具
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
  • Reference
GitHub (opens new window)
  • MySQL8.0详解与实战

  • MySQL面试指南

  • Redis从入门到高可用

  • Elastic-Stack

    • 第01章-Elasticsearch入门
    • 第02章-倒排索引与分词
    • 第03章-Mapping设置
    • 第04章-Search API
      • 2.1 搜索方式介绍
      • 2.2 搜索语法
        • 匹配规则
        • 布尔操作符
        • 范围查询,支持数值和日期
        • 通配符查询
        • 正则表达式匹配
        • 模糊匹配 fuzzy query
        • 近似度查询 proximity search
      • 3.1 搜索方式介绍
      • 3.2 Query DSL
      • 3.3 相关性算分
        • 3.3.1 相关性算分因素
        • 3.3.2 相关性算分模型
      • 4.1 字段查询
        • 4.1.1 全文查询
        • Match Query
        • Match Phrase Query
        • Query String Query
        • Simple Query String Query
        • 4.1.2 单词级查询
        • Term Query
        • Range Query
      • 4.2 复合查询
        • 4.2.1 constant_score query
        • 4.2.2 bool query
      • 6.1 文档计数
      • 6.2 文档字段过滤
    • 第05章-分布式特性介绍
    • 第06章-Search的运行机制
    • 第07章-聚合分析
    • 第08章-数据建模
    • 第09章-集群调优建议
  • 数据库
  • Elastic-Stack
CodeAshen
2023-02-10
目录

第04章-Search API

# 一、Search API 概览

实现对 es 中存储的数据进行查询分析,endpoint 为 _search,如下所示:

image-20201226175946805

查询主要有两种形式

  • URI Search:操作简便,方便通过命令行测试,仅包含部分查询语法
  • Request Body Search:es 提供的完备查询语法 Query DSL (Domain Specific Language)

image-20201226180123424

# 二、URI Search

# 2.1 搜索方式介绍

通过 url query 参数来实现搜索,常用参数如下:

  • q:指定查询的语句,语法为 Query String Syntax
  • df:q 中不指定字段时默认查询的字段,如果不指定,es 会查询所有字段
  • sort:排序
  • from, size:用于分页
  • timeout:指定超时时间,默认不超时

image-20201226180557610

# 2.2 搜索语法

# 匹配规则

  • term 与 phrase:

    q=alfred way    等效于 alfred OR way
    q="alfred way"  词语查询,要求先后顺序
    
    1
    2
  • 泛查询:q=alfred 等效于在所有字段去匹配该 term

  • 指定字段:q=name:alfred

  • Group 分组设定:使用括号指定匹配的规则

    q=(quick OR brown) AND fox 
    q=status:(active OR pending) title:(full text search)
    
    1
    2

可以通过加 profile 请求体,查看实际查询条件

image-20201226183111763

image-20201226183215912

# 布尔操作符

  • AND(&&), OR(|), NOT(!)

    q=name:(tom NOT lee)   注意大写,不能小写
    
    1
  • + - 分别对应 must 和 must_not

    q=name:(tom+lee-alfred)`,`q=name:(lee&&lalfred)|(tom&&lee&&lalfred))`
    
    1

    + 在 url 中会被解析为空格,要使用 encode 后的结果才可以,为 %2B

# 范围查询,支持数值和日期

  • 区间写法,闭区间用 [],开区间用 {}

    age:[1 TO 10]  意为 1<=age<=10
    age:[1 TO 10}  意为 1<=age<10
    age:[1 TO]     意为 age>=1
    age:[* TO 10]  意为 age<=10
    
    1
    2
    3
    4
  • 算数符号写法

    age:>=1
    age:(>=1&&<=10) 或者 age:(+>=1+<=10)
    
    1
    2

# 通配符查询

  • ? 代表1个字符,* 代表0或多个字符

    name:t?m
    name:tom*
    name:t*m*
    
    1
    2
    3
  • 通配符匹配执行效率低,且占用较多内存,不建议使用

  • 如无特殊需求,不要将 ? 或 * 放在最前面

# 正则表达式匹配

name:/[mb]oat/

# 模糊匹配 fuzzy query

name:roam~1:匹配与 roam 差 1 个 character 的词,比如 foam、roams 等

# 近似度查询 proximity search

"fox quick"~5:以 term 为单位进行差异比较,比如 "quick fox","quick brown fox" 都会被匹配

# 三、Request Body Search

# 3.1 搜索方式介绍

将查询语句通过 http request body 发送到 es,主要包含如下参数

  • query:符合 Query DSL 语法的查询语句
  • from、size、timeout、sort 等等

# 3.2 Query DSL

基于JSON定义的查询语言,主要包含如下两种类型:

  • 字段类查询:如 term, match, range 等,只针对某一个字段进行查询
  • 复合查询:如 bool 查询等,包含一个或多个字段类查询或者复合查询语句

具体参考官方文档:Query DSL (opens new window)

Query DSL 结构包含主要包含下图部分,后面会详细介绍相关查询的含义和语法。

image-20210809022421414

# 3.3 相关性算分

在介绍详细介绍查询方式之前,先学习下 es 的相关性算分。

相关性算分是指文档与查询语句间的相关度,英文为 relevance,通过倒排索引可以获取与查询语句相匹配的文档列表,那么如何 将最符合用户查询需求的文档放到前列 呢?本质是一个排序问题,排序的依据是相关性算分。

image-20201226193837601

# 3.3.1 相关性算分因素

相关性算分的几个重要概念如下:

  • Term Frequency(TF) 词频,即单词在该文档中出现的次数。词频越高,相关度越高
  • Document Frequency(DF) 文档频率,即单词出现的文档数
  • Inverse Document Frequency(IDF) 逆向文档频率,与文档频率相反,简单理解为1/DF。即单词出现的文档数越少,相关度越高
  • Field-length Norm 文档越短,相关性越高

# 3.3.2 相关性算分模型

ES目前主要有两个相关性算分模型,如下:

  1. TF/IDF 模型
  2. BM25 模型,5.x 之后的默认模型

TF/IDF 模型 是 Lucene 的经典模型,其计算公式如下

image-20201226194233000

可以通过 explain 参数来查看具体的计算方法,但要注意:

  • es 的算分是按照 shard 进行的,即 shard 的分数计算是相互独立的,所以在使用 explain 的时候注意分片数。
  • 可以通过设置索引的分片数为 1 来避免这个问题

image-20201226200524827

BM25 模型 中 BM 指 Best Match,25 指迭代了 25 次才计算方法,是针对 TF/IDF 的一个优化,其计算公式如下:

image-20201226200737542

BM25 相比 TF/IDF 的一大优化是降低了 TF(词频)在过大时的权重

image-20201226200925270

至此,了解了相关性算分之后,开始详细介绍查询方式和语法。

# 四、字段查询和复合查询

前面介绍 Query DSL 时,提到 Query DSL 主要包含包含字段类型查询和符合查询。

# 4.1 字段查询

字段类查询主要包括以下两类:

  • 全文查询:针对 text 类型的字段进行全文检索,会对查询语句先进行分词处理,如 match,match_phrase 等 query 类型。
  • 单词级查询:不会对查询语句做分词处理,直接去匹配字段的倒排索引,如 term,terms,range 等。

# 4.1.1 全文查询

全文查询使你能够搜索分析过的文本字段,例如电子邮件正文。查询时使用的分词器和索引时分词器相同。

具体可参考官方文档:Full text queries (opens new window)

全文查询包含以下具体方式:

# Match Query

  • 对字段作全文检索,最基本和常用的查询类型,API示例如下

image-20201226192654312

image-20201226192834774

  • Match Query具体流程如下

image-20201226193018447

  • 通过 operator 参数可以控制单词间的匹配关系,可选项为 or 和 and

    以下示例表示 文档中 alfred 和 way 必须同时存在

image-20201226193147450

  • 通过 minimum_should_match 参数可以控制需要匹配的单词数

    以下示例表示 文档最少含有条件中的两个单词

image-20201226193340270

# Match Phrase Query

对字段作检索,有顺序要求,API 示例如下:

image-20201226201007930

image-20201226201058092

  • 通过 slop 参数可以控制单词间的间隔

    以下示例表示 关键词之间允许存在一个词的间隔距离

image-20201226201120244

image-20201226201237451

# Query String Query

类似于 URI Search 中的 q 参数查询

image-20201226201542037

image-20201226201740320

# Simple Query String Query

类似 Query String,但是会忽略错误的查询语法,并且仅支持部分查询语法

其常用的逻辑符号如下,不能使用 AND、OR、NOT 等关键词:

  • + 代指 AND
  • | 代指 OR
  • - 代指 NOT

image-20201226201923225

# 4.1.2 单词级查询

使用单词级别的查询,根据结构化数据中的精确值查找文档。与全文查询不同,词级查询不进行分词。相反,单词级查询与文档中的字段进行精确匹配。

具体可参考官方文档:Term level queries (opens new window)

单词级查询包含以下具体方式:

# Term Query

将查询语句作为整个单词进行查询,即不对查询语句做分词处理,如下所示:

image-20201226202151991

使用 terms 一次传入多个单词进行查询,如下所示:

image-20201226202244803

# Range Query

范围查询主要针对数值和日期类型,如下所示:

image-20201226202352941

针对日期做查询,如下所示

image-20201226202458420

针对日期提供的一种更友好地计算方式,格式如下:

image-20201226202553652

主要时间单位:y-years,M-months,w-weeks,d-days,h-hours,m-minutes,s-seconds

假设 now 为 2018-01-02 12:00:00,那么如下的计算结果实际为:

image-20201226202813590

# 4.2 复合查询

复合查询是指包含字段类查询或复合查询的类型,主要包括以下几类:

  • constant_score query:包装另一个查询的查询,但在过滤器上下文中执行它。
  • bool query:组合一个或多个布尔查询子句。
  • dis_max query:接受多个查询并返回与任何查询子句匹配的文档。
  • function_score query:允许修改查询结果文档的相关性得分。
  • boosting query:返回匹配 positive 子句的文档,同时减少也匹配 negative 子句文档的分数。

具体参考官方文档:Compound Queries (opens new window)

下面重点介绍 constant_score query 和 bool query

# 4.2.1 constant_score query

包装过滤器查询,并将所有结果的相关性得分都设置成 boost 参数设置的值,默认为 1.0,然后将过滤后的文档放回。

image-20201226203228938

# 4.2.2 bool query

布尔查询,由一个或多个布尔子句组成,主要包含如下4个:

子句 含义
filter 只过滤符合条件的文档,不计算相关性得分
must 文档必须符合 must 中的所有条件,会影响相关性得分
must_not 文档必须不符合 must_not 中的所有条件,不会影响相关性得分
should 文档可以符合 should 中的条件,会影响相关性得分

Bool 查询的 API 如下所示

image-20201226203635765

Filter 查询只过滤符合条件的文档,不会进行相关性算分

  • es 针对 filter 会有智能缓存,因此其执行效率很高
  • 做简单匹配查询且不考虑算分时,推荐使用 filter 替代 query 等

image-20201226203803009

must

image-20201226203922939

must_not

image-20201226204105896

should

should 使用分两种情况:

  1. bool 查询中只包含 should,不包含 must 查询
  2. bool 查询中同时包含 should 和 must 查询

只包含 should 时,文档必须满足至少一个条件

minimum should_match 可以控制满足条件的个数或者百分比

image-20201226204204838

同时包含 should 和 must 时,文档不必满足 should 中的条件,但是如果满足条件,会增加相关性得分

image-20201226204303800

# 五、Query 和 Filter 上下文

默认情况下,Elasticsearch 按相关性分数对匹配的搜索结果进行排序,相关性分数衡量每个文档与查询的匹配程度。虽然每种查询类型可以不同地计算相关性分数,但分数计算还取决于查询子句是在查询还是过滤器上下文中运行。

在 Query 上下文中,查询子句回答了 “此文档与此查询子句匹配程度如何?” 除了判断文档是否匹配外,查询子句还会计算 _score 元数据字段中的相关性分数 。

在 Filter 上下文中,查询子句回答问题 “此文档是否与此查询子句匹配?”,答案是简单的“是”或“否”——不计算分数。过滤上下文主要用于过滤查询结果文档。

image-20201226204502324

Query 和 Filter 上下文使用示例:

image-20201226204553616

具体参考官方文档:Query and filter context (opens new window)

# 六、文档计数和字段过滤

# 6.1 文档计数

获取符合条件的文档数,endpoint 为 _count

image-20201226204633445

# 6.2 文档字段过滤

过滤返回结果中 _source 中的字段,主要有如下几种方式:

image-20201226204730854

编辑 (opens new window)
上次更新: 2023/06/04, 12:34:19
第03章-Mapping设置
第05章-分布式特性介绍

← 第03章-Mapping设置 第05章-分布式特性介绍→

最近更新
01
第01章-RabbitMQ导学
02-10
02
第02章-入门RabbitMQ核心概念
02-10
03
第03章-RabbitMQ高级特性
02-10
更多文章>
Theme by Vdoing | Copyright © 2020-2023 CodeAshen | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式