带你读《Elastic Stack 实战手册》之34:——3.4.2.17.3.全文搜索/精确搜索(9)

本文涉及的产品
Elasticsearch Serverless通用抵扣包,测试体验金 200元
简介: 带你读《Elastic Stack 实战手册》之34:——3.4.2.17.3.全文搜索/精确搜索(9)


《Elastic Stack 实战手册》——三、产品能力——3.4.入门篇——3.4.2.Elasticsearch基础应用——3.4.2.17.Text analysis, settings 及 mappings——3.4.2.17.3.全文搜索/精确搜索(8) https://developer.aliyun.com/article/1229934



四、基于全文的查询方法

 

基于全文的方法主要有:match/match_phrase/match_phrase_prefix/multi_match/match_bool_prefix/query_string/simple_query_string/intervals/combined_fields 九种方法。

 

在全文查询的复杂方法中,很多基于 match 查询的参数,如:analyzer, boost, operator, minimum_should_match, fuzziness, lenient, prefix_length, max_expansions, fuzzy_rewrite,zero_terms_query 和 cutoff_frequency 都能在其它方法中使用。

 

4.1 match

 

match 查询是一个基础的全文搜索方法,它会将查询的短语进行分词后对某一字段进行查询。match 查询对被分词后的 token 并没有强顺序关系,只要匹配就可以返回。


使用方法:

PUT my-index-000001
POST my-index-000001/_mapping
{"properties":{"message":{"type":"text"}}}
POST my-index-000001/_bulk
{ "index": { "_id": 1 }}
{ "message": "this is a test" }
GET my-index-000001/_search
{
  "query": {
    "match": {
      "message": {
        "query": "this is a test"
      }
    }
  }
}

参数:

 

l analyzer:设置将查询的短语转换成 token 的分词器。默认与字段索引时的分词器一致,即 mapping 设置的 analyzer 参数。如果没有设置,则使用默认的分词。

l auto_generate_synonyms_phrase_query如果为 true,为多项同义词自动生成短语查询。这个与分词器中设置的同义词相关。默认值为 true。

l fuzziness:允许匹配的最大编辑距离。可以是 0/1/2/AUTO

l max_expansions:创建的最大变体或者扩展词项数。默认为 50。

l prefix_length:在创建展开时保持不变的起始字符数。默认值为 0。

l fuzzy_transpositions:指编辑是否包括两个相邻字符的换位( ab → ba )。默认值为 true。

l lenient:如果为真,则忽略基于格式的错误,例如为数字字段提供 text 查询值。默认值为 false。

l operator:查询文本中的布尔逻辑。

OR:默认值。例如,将查询值 “capital of Hungary” 解释为 “capital” 或者 “of” 或者 “Hungary”。

AND:例如,将查询值 “capital of Hungary” 解释为 “capital” 和 “of” 和 “Hungary”。

l minimum_should_match:要返回的文档必须匹配的最小词项数。例如,“capital of Hungary” 被分词成 “capital”、“of”、“Hungary” 三个词项,minimum_should_match 设置为 2,则文档必须匹配前面三个词项中的两个才能返回。

l zero_terms_query:指示如果分析器删除所有词项时(例如使用停顿词分词器时),是否不返回文档。

none:默认值。如果分词器删除所有词项时,则不返回文档。

all:与none相反,返回所有文档。

 

相关使用方法:

 

match 查询的 operator 和 minimum_should_match

 

先创建一个测试索引和相关测试数据


PUT my-index-000001
POST my-index-000001/_mapping
{
  "properties": {
    "message": {
      "type": "text"
    }
  }
}
PUT my-index-000001/_doc/1
{ "message":"this is test"}
PUT my-index-000001/_doc/2
{ "message":"this is a test again"}
PUT my-index-000001/_doc/3
{ "message":"this is  not a test"}

使用默认的分词器,可以看到几个文档会被解析成 "this"、"is"、"a"、"test"、"again"、"not" 这几个词项。

 

POST _analyze
{
  "text": [
    "this is test",
    "this is a test again",
    "this is  not a test"
  ]
}
# 返回结果
{
  "tokens" : [
    {
      "token" : "this",
      "start_offset" : 0,
      "end_offset" : 4,
      "type" : "<ALPHANUM>",
      "position" : 0
    },
    {
      "token" : "is",
      "start_offset" : 5,
      "end_offset" : 7,
      "type" : "<ALPHANUM>",
      "position" : 1
},
   {
      "token" : "test",
      "start_offset" : 8,
      "end_offset" : 12,
      "type" : "<ALPHANUM>",
      "position" : 2
    },
    {
      "token" : "this",
      "start_offset" : 13,
      "end_offset" : 17,
      "type" : "<ALPHANUM>",
      "position" : 3
    },
    {
      "token" : "is",
      "start_offset" : 18,
      "end_offset" : 20,
      "type" : "<ALPHANUM>",
      "position" : 4
    },
    {
      "token" : "a",
      "start_offset" : 21,
      "end_offset" : 22,
      "type" : "<ALPHANUM>",
      "position" : 5
    },
    {
      "token" : "test",
      "start_offset" : 23,
      "end_offset" : 27,
      "type" : "<ALPHANUM>",
        "position" : 6
    },
    {
      "token" : "again",
      "start_offset" : 28,
      "end_offset" : 33,
      "type" : "<ALPHANUM>",
      "position" : 7
    },
    {
      "token" : "this",
      "start_offset" : 34,
      "end_offset" : 38,
      "type" : "<ALPHANUM>",
      "position" : 8
    },
    {
      "token" : "is",
      "start_offset" : 39,
      "end_offset" : 41,
      "type" : "<ALPHANUM>",
      "position" : 9
    },
    {
      "token" : "not",
      "start_offset" : 43,
      "end_offset" : 46,
      "type" : "<ALPHANUM>",
      "position" : 10
    },
    {
      "token" : "a",
      "start_offset" : 47,
      "end_offset" : 48,
      "type" : "<ALPHANUM>",
      "position" : 11
    },
    {
      "token" : "test",
      "start_offset" : 49,
      "end_offset" : 53,
      "type" : "<ALPHANUM>",
      "position" : 12
    }
  ]
}

match 查询 "this is a test",这个短语也会被分词成 "this"、"is"、"a"、"test"


POST _analyze
{
  "text": [
    "this is a test"
  ]
}
# 返回结果
{
  "tokens" : [
    {
      "token" : "this",
      "start_offset" : 0,
      "end_offset" : 4,
      "type" : "<ALPHANUM>",
      "position" : 0
    },
{
      "token" : "is",
      "start_offset" : 5,
      "end_offset" : 7,
      "type" : "<ALPHANUM>",
      "position" : 1
    },
    {
      "token" : "a",
      "start_offset" : 8,
      "end_offset" : 9,
      "type" : "<ALPHANUM>",
      "position" : 2
    },
    {
      "token" : "test",
      "start_offset" : 10,
      "end_offset" : 14,
      "type" : "<ALPHANUM>",
      "position" : 3
    }
  ]
}

如果按照 match 默认 or 的查询逻辑,只要有一个词项匹配就会返回,那么测试的三个文档将全部返回。


GET /_search
{
  "query": {
    "match": {
      "message": {
        "query": "this is a test",
        "operator": "or"
      }
    }
  }
}
# 返回结果
{
  "took" : 16,
  "timed_out" : false,
  "_shards" : {
    "total" : 48,
    "successful" : 48,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 0.5298672,
    "hits" : [
      {
        "_index" : "my-index-000001",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 0.5298672,
        "_source" : {
          "message" : "this is  not a test"
        }
      },
      {
        "_index" : "my-index-000001",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.5298672,
        "_source" : {
          "message" : "this is a test again"
        }
      },
      {
        "_index" : "my-index-000001",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.30433932,
        "_source" : {
          "message" : "this is test"
        }
      }
    ]
  }
}


但是如果设置 minimum_should_match 为 4,则需要有四个词项匹配,那么只有文档 2 和 3 符合了。


GET /_search
{
  "query": {
    "match": {
      "message": {
        "query": "this is a test",
        "operator": "or",
        "minimum_should_match": 4
      }
}
  }
}
# 返回结果
{
  ......
   "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 0.5298672,
    "hits" : [
      {
        "_index" : "my-index-000001",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 0.5298672,
        "_source" : {
          "message" : "this is  not a test"
        }
      },
      {
        "_index" : "my-index-000001",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.5298672,
        "_source" : {
          "message" : "this is a test again"
        }
      }
    ]
  }
}


然后,再看一下 operator 为 and 的时候。其实,可以发现 and 的情况与之前设置 minimum_should_match 为 4 的查询一致,因为两者都代表查询时,每个词项都需要匹配上。


GET /_search
{
  "query": {
    "match": {
      "message": {
        "query": "this is a test",
        "operator": "and"
      }
    }
  }
}
# 返回结果
{
 ......
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 0.5298672,
    "hits" : [
      {
        "_index" : "my-index-000001",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 0.5298672,
        "_source" : {
          "message" : "this is  not a test"
        }
      },
      {
        "_index" : "my-index-000001",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.5298672,
        "_source" : {
          "message" : "this is a test again"
        }
      }
    ]
  }
}

match 中的模糊查询

 

fuzziness 的一系列参数可以使 match 解析出的词项进行模糊匹配。具体相关参数的使用方法与 fuzzy 查询一致,因此不详细展开了。

 

来看下面的例子:


GET /_search
{
  "query": {
    "match": {
      "message": {
        "query": "this is a test",
        "fuzziness": "auto"
        , "operator": "and"
      }
    }
  }
}
# 返回结果
{
  ......
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 0.50886154,
    "hits" : [
      {
        "_index" : "my-index-000001",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 0.50886154,
        "_source" : {
          "message" : "this is  not a test"
        }
      },
      {
        "_index" : "my-index-000001",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.50886154,
        "_source" : {
          "message" : "this is a test again"
        }
      }
    ]
  }
}


很明显,虽然查询的内容中错误的把 “test” 写成了 “testt”,但是经过 fuzziness 参数的调整,达到了纠错的效果。



《Elastic Stack 实战手册》——三、产品能力——3.4.入门篇——3.4.2.Elasticsearch基础应用——3.4.2.17.Text analysis, settings 及 mappings——3.4.2.17.3.全文搜索/精确搜索(10) https://developer.aliyun.com/article/1229931

 

相关实践学习
以电商场景为例搭建AI语义搜索应用
本实验旨在通过阿里云Elasticsearch结合阿里云搜索开发工作台AI模型服务,构建一个高效、精准的语义搜索系统,模拟电商场景,深入理解AI搜索技术原理并掌握其实现过程。
ElasticSearch 最新快速入门教程
本课程由千锋教育提供。全文搜索的需求非常大。而开源的解决办法Elasricsearch(Elastic)就是一个非常好的工具。目前是全文搜索引擎的首选。本系列教程由浅入深讲解了在CentOS7系统下如何搭建ElasticSearch,如何使用Kibana实现各种方式的搜索并详细分析了搜索的原理,最后讲解了在Java应用中如何集成ElasticSearch并实现搜索。 &nbsp;
相关文章
|
存储 Kubernetes 负载均衡
k8s详解
@[TOC](目录) Kubernetes(简称 k8s)是一个开源的容器编排系统,用于自动化部署、扩展和管理容器化应用程序。本篇详解将介绍 k8s 的核心概念、架构和使用方法,帮助读者深入理解 k8s 并掌握其基本操作。 # 一、k8s 核心概念 1.1 容器 容器是一种轻量级、可移植的虚拟化技术,用于打包和运行应用程序。容器可以共享主机操作系统的内核,从而提高部署效率和资源利用率。常见的容器技术包括 Docker、Kubernetes Pod、LXC 等。 1.2 Namespace Namespace 是 k8s 中的资源隔离单元,用于对 k8s 对象进行命名空间隔离。通过创建 Name
708 0
WK
|
12月前
|
存储 移动开发 前端开发
HTML5和CSS5有什么区别
HTML5和CSS5在网页设计中扮演不同角色。HTML5是超文本标记语言的第五版,通过新特性如实时更新、跨平台运行及更好的安全性等,定义网页内容和结构。尽管常说CSS5,实际最新的CSS版本包含多个模块如CSS Grid和Flexbox,主要用于控制网页布局和样式,提供强大的选择器、动画支持和响应式设计,与HTML5相辅相成,共同构建现代网页的基础架构。
WK
286 3
|
11月前
|
XML Java Maven
在 Cucumber 测试中自动将 Cucumber 数据表映射到 Java 对象
在 Cucumber 测试中自动将 Cucumber 数据表映射到 Java 对象
194 7
|
前端开发 JavaScript API
react 常用的状态管理
【8月更文挑战第29天】react 常用的状态管理
263 1
|
Ubuntu Shell Linux
【Docker最佳实践】Windows上安装Docker及常见问题解决
一、环境准备: 1. window 7 2. 支持“ Hardware Virtualization Technology”,并且,“virtualization ”可用 3. Docker Toolbox (官网地址:https://www.docker.com/products/docker-desktop 阿里云镜像: http://mirrors.aliyun.com/docker-toolbox/windows/docker-toolbox/)【下载最新版本】
7387 0
|
Arthas 监控 Java
金石原创 |【JVM实战系列】「监控调优体系」实战开发arthas-spring-boot-starter监控你的微服务是否健康!
金石原创 |【JVM实战系列】「监控调优体系」实战开发arthas-spring-boot-starter监控你的微服务是否健康!
291 0
|
机器学习/深度学习 自然语言处理 异构计算
完全小白的pycharm深度学习调试+for循环断点条件设置
完全小白的pycharm深度学习调试+for循环断点条件设置
750 1
|
Java 缓存 测试技术
Groovy&Java动态编译执行
Groovy&Java动态编译执行 工作中,遇到部分业务经常动态变化,或者在不发布系统的前提下,对业务规则进行调整。那么可以将这部分业务逻辑改写成Groovy脚本来执行,那么就可以在业务运行过程中动态更改业务规则,达到快速响应。
2096 0
|
Python Windows
python 如何在windows 64系统下安装salem 库
最近,需要用到geopandas + salem裁剪数据,对于salem库的安装,比较麻烦,在我的尝试下,终于算是成功安装了,简单记录一下安装记录,希望可以帮助到有需要的兄弟姐妹们 。
python 如何在windows 64系统下安装salem 库
|
Arthas 存储 运维
60-微服务技术栈(高级):在线检测工具Arthas(实现CPU排查与代码热更新)
线上代码经常会出现CPU占用过高的情况,按以往经验我会使用top指令,进一步借助于jstack去查看具体信息从而进行问题排查,但基本上都逃不过需要重新发包的局面,即使是一个增量包,应用也需要短暂停启。后来运维大兄弟让我试一下Arthas,说是可以进行代码的热更新操作,正好来试一下。
543 0