前言

Elasticsearch 中,Term 查询和全文查询是两种完全不同的处理方式,在上一篇我们也简单对比了 Term 查询和全文查询中的 Phrase 中的区别,那么本文就彻底的来理清这两种查询之间的关系。

我们重新创建一个新的索引 index_002,并插入以下数据

POST /_bulk
{"index":{"_index":"index_002"}}
{"id":"1","name":"lonely wolf","address":null,"count":1}
{"index":{"_index":"index_002"}}
{"id":"2","name":"lonely hello wolf","address":[],"count":3}
{"index":{"_index":"index_002"}}
{"id":"3","name":"lonely hello word wolf","address":"[广东]","count":1}
{"index":{"_index":"index_002"}}
{"id":"4","name":"Lonely Wolf","address":"['广东','深圳']","count":2}
{"index":{"_index":"index_002"}}
{"id":"5","name":"wolf","address":null,"count":1}

Term 查询

Term 查询一般表达的是最小单位查询,也就是说对我们传入的关键字会作为一个整体进行查询,而不会进行分词。

如下查询,满足条件的只有第一条数据,需要注意的是对 text 类型字段需要加上 .keyword

POST index_001/_search
{
"query": {
"term": {
"name.keyword": {
"value": "lonely wolf"
}
}
}
}

这里如果不加上 .keyword 则不会返回任何结果,这是因为 text 类型的字段会被倒排索引进行存储,倒排索引会利用分析器将文本进行分词,我们可以利用分词器来查看下分词结果:

POST /_analyze
{
"analyzer": "standard",
"text": ["lonely wolf"]
}

可以看到,lonely wolf 被分成了 lonelywolf 两个单词,所以我们将 lonely wolf 作为一个进行查询自然是无法查询到结果的。

这里有个地方需要注意,如果我们存入的是大写单词,如 Lonely Wolf,分词器也是一样的结果,也就是会将大写字母统一转化为小写进行存储,所以进行全文查询的时候也是无法查询出结果。

exists 查询

用来判定是否存在某一个字段,返回包含字段的任何索引值的文档。

GET index_002/_search
{
"query": {
"exists": {
"field": "address"
}
}
}

这里返回的结果就是第三条和第四条数据,像 null 值和空数组 [] 不会被返回。

如果想要返回 null 值或者空数组 [] 的数据,那么可以利用 bool 查询的 must_not 语句:

GET index_002/_search
{
"query": {
"bool": {
"must_not": [
{
"exists": {"field": "address"}
}
]
}
}
}

fuzzy 查询

用于近似查询,比如我们有时候在用百度搜索的时候,输错了字会被纠正:

一般情况下有一个单词错误的情况下,fuzzy 查询可以找到另一个近似的词来代替,主要有以下场景:

  • 修改一个单词,如:box--->fox
  • 移除一个单词,如:black-->lack
  • 插入一个单词,如:sic-->sick
  • 转换两个单词顺序,如:act-->cat

为了可以查询到这种近似的单词,fuzzy 查询需要创建一个所有近似词的集合,这样搜索的时候就可以采用精确查询找到近似的词来代替查询。

比如下面这个查询就可以查询出前面四条数据,同样的,value 修改为 loneyllonelyyloneyle 都能查询出前面四条数据:

GET index_002/_search
{
"query": {
"fuzzy": {
"name": {
"value": "lonel"
}
}
}
}

ids 查询

通过文档 id 进行查询返回,这里的 id 为文档中的 _id

GET index_002/_search
{
"query": {
"ids": {
"values": ["id1","id2"]
}
}
}

prefix 查询

通过指定字段的前缀进行查询。

GET index_002/_search
{
"query": {
"prefix": {
"name": {
"value": "lo"
}
}
}
}

range 查询

通过范围进行查询。

GET index_002/_search
{
"query": {
"range": {
"id": {
"gte": 1,
"lte": 2
}
}
}
}

其中:

  • gt:表示大于。
  • gte:表示大于等于。
  • lt:表示小于。
  • lte:表示小于等于。

这种范围查询还可以用于日期的范围查询,此时将会对日期进行毫秒数转换后进行查询,如下面的例子就是查询昨天到今天的区间,而且可以通过 time_zone 指定时区:

GET _search
{
"query": {
"range" : {
"timestamp" : {
"gte" : "now-1d/d",
"lt" : "now/d"
}
}
}
}

regexp 查询

通过正则表达式进行查询。如下例子可以查询出 lon 开头的所有数据:

GET index_002/_search
{
"query": {
"regexp": {
"name": "lon.*"
}
}
}

term 查询

返回一个或者多个单词精确匹配的文档。

# 返回前面四条数据
GET index_002/_search
{
"query": {
"term": {
"name": {
"value": "lonely"
}
}
}
}
# 只返回第一条数据
GET index_002/_search
{
"query": {
"term": {
"name.keyword": {
"value": "lonely wolf"
}
}
}
}

terms 查询

terms 查询和 term 查询是一个含义,区别只是 terms 可以一次精确匹配多个词。

# 返回全部五条数据
GET index_002/_search
{
"query": {
"terms": {
"name": [
"lonely",
"wolf"
]
}
}
}

terms_set 查询

terms_set 查询和 terms 查询是一样的查询规则,不同的是 terms_set 查询可以定义匹配词项的数量,定义的数量只能从文档中的某一列中进行获取或者使用脚本进行配置:

# 这里只能查询第一和第三两条数据,因为 `Wolf` 中的首字母大写,无法被精确匹配上,count列不能是text类型
GET index_002/_search
{
"query": {
"terms_set": {
"name": {
"terms": [
"lonely",
"Wolf"
],
"minimum_should_match_field": "count"
}
}
}
}

type 查询

指定类型查询,type 类型在 7.0 版本已经标注为过期,8.0 版本已经被废弃。

wildcard 查询

通过通配符进行查询,这个可以理解为是简易版本的正则表达式查询:

GET index_002/_search
{
"query": {
"wildcard": {
"name": {
"value": "lone*"
}
}
}
}

全文查询

高级全文查询通常用于对全文字段 text 类型(比如电子邮件的正文)进行全文查询。全文查询在搜索和索引时,都会对字段进行分词处理,查询之前会先对输入的词进行分词处理,然后对每个词项进行查询,最后将结果进行合并,并根据算分结果将结果进行返回。

全文查询也包括很多种,在这里我们主要介绍 match 查询和 match_phrase 查询。

match 查询

match 查询是执行全文搜索的标准查询,包括模糊匹配选项。如下就是一个标准的 match 查询语句:

# 返回全部5条数据
POST index_002/_search
{
"query": {
"match": {
"name": "lonely wolf"
}
}
}

对比 term 查询:

# 没有满足条件的结果
POST index_002/_search
{
"query": {
"term": {
"name": "lonely wolf"
}
}
}
# 返回第一条数据
POST index_002/_search
{
"query": {
"term": {
"name.keyword": "lonely wolf"
}
}
}

根据上面几个查询的结果我们可以得出 term 查询和全文 match 查询的区别:

  • term 查询会将搜索关键字作为一个整体进行查询。
  • match 查询会将搜索关键字进行分词,且分词后默认是 or 的关系。

根据这两个结论,也可以很明显知道,一般不对 text 类型字段采用 term 查询,因为 text 类型字段会被分词索引,可能会导致无法被 term 查询匹配出结果。

再看下面这个例子,会返回第二和第三两条数据(分词后的搜索和顺序无关):

# 查询出最少匹配中3个词项的结果
POST index_002/_search
{
"query": {
"match": {
"name": {
"query": "hello wolf lonely",
"operator": "or",
"minimum_should_match": 3
}
}
}
}

match_phrase 查询

match_phrase 会将输入的搜索关键字作为一个短语进行查询,这点看来类似于 term 查询,但是 match_phrase 查询内嵌了一个参数 slot 用来定义短语中允许的空隙,默认是 0 表示中间不允许有其他词:

POST index_002/_search
{
"query": {
"match_phrase": {
"name": {
"query": "lonely wolf"
}
}
}
}

这条语句的结果就能查询出第一和第四条数据,注意,虽然第四条数据中的 lonely wolf 是大写字母开头,但是索引的时候会将其转为小写进行索引,所以也能查询出结果。

此时我们加入 slot=1 条件进行查询,表示允许短语之间存在一个间隙,所以此时能查询出第二条数据:

POST index_002/_search
{
"query": {
"match_phrase": {
"name": {
"query": "hello wolf lonely",
"slop": 1
}
}
}
}

总结

本文主要讲述了 Term 查询和全文查询中 match 查询的区别,总结起来主要有以下几点:

  1. Term 查询对搜索关键字不会进行分词处理,而是作为一个整体进行查询。
  2. 全文查询如 match 等查询,会对搜索关键字进行分词,并对每个词项进行搜索,默认 or 的关系进行合并,并最终算法返回结果。
  3. Text 类型字段,索引时会进行分词,大写字母会转成小写,所以如果用 Term 或者 match_phrase 查询时要注意因分词而对查询结果产生的影响。

Elasticsearch中的Term查询和全文查询的更多相关文章

  1. elasticsearch中的mapping映射配置与查询典型案例

    elasticsearch中的mapping映射配置与查询典型案例 elasticsearch中的mapping映射配置示例比如要搭建个中文新闻信息的搜索引擎,新闻有"标题".&q ...

  2. ES 22 - Elasticsearch中如何进行日期(数值)范围查询

    目录 1 范围查询的符号 2 数值范围查询 3 时间范围查询 3.1 简单查询示例 3.2 关于时间的数学表达式(date-math) 3.3 关于时间的四舍五入 4 日期格式化范围查询(format ...

  3. Elasticsearch+Mongo亿级别数据导入及查询实践

    数据方案: 在Elasticsearch中通过code及time字段查询对应doc的mongo_id字段获得mongodb中的主键_id 通过获得id再进入mongodb进行查询   1,数据情况: ...

  4. 使用Hive或Impala执行SQL语句,对存储在Elasticsearch中的数据操作(二)

    CSSDesk body { background-color: #2574b0; } /*! zybuluo */ article,aside,details,figcaption,figure,f ...

  5. 使用Hive或Impala执行SQL语句,对存储在Elasticsearch中的数据操作

    http://www.cnblogs.com/wgp13x/p/4934521.html 内容一样,样式好的版本. 使用Hive或Impala执行SQL语句,对存储在Elasticsearch中的数据 ...

  6. Elasticsearch 5.0 中term 查询和match 查询的认识

    Elasticsearch 5.0 关于term query和match query的认识 一.基本情况 前言:term query和match query牵扯的东西比较多,例如分词器.mapping ...

  7. 在Elasticsearch中查询Term Vectors词条向量信息

    这篇文章有点深度,可能需要一些Lucene或者全文检索的背景.由于我也很久没有看过Lucene了,有些地方理解的不对还请多多指正. 更多内容还请参考整理的ELK教程 关于Term Vectors 额, ...

  8. Elasticsearch Query DSL 整理总结(一)—— Query DSL 概要,MatchAllQuery,全文查询简述

    目录 引言 概要 Query and filter context Match All Query 全文查询 Full text queries 小结 参考文档 引言 虽然之前做过 elasticse ...

  9. ElasticSearch中的简单查询

    前言 最近修改项目,又看了下ElasticSearch中的搜索,所以简单整理一下其中的查询语句等.都是比较基础的.PS,好久没写博客了..大概就是因为懒吧.闲言少叙书归正传. 查询示例 http:// ...

随机推荐

  1. C# 给PDF签名时添加时间戳的2种方法(附VB.NET代码)

    在PDF添加签名时,支持添加可信时间戳来保证文档的法律效应.本文,将通过C#程序代码介绍如何添加可信时间戳,可通过2种方法来实现.文中附上VB.NET代码,有需可供参考. 一.程序运行环境 编译环境: ...

  2. CentOS 7磁盘寻找不到,卡在sulogin,造成的开机失败问题--Error getting authority...

    今天早上使用内网gitlab仓库的时候,发现页面无法打开,ssh也无法连接. 到机房接上显示器,发现如下错误: Error getting authority: Error initializing ...

  3. LNAMP架构项目一

    一.第一阶段 假设:公司初期只有一台web服务器,搭建Web服务器的脚本如下: 1 #检查环境 2 setenforce 0 &> /dev/null 3 sed -i s/=enfor ...

  4. VUE如何关闭代码规范extra semiclon/VUE新手必看-(转载)

    VUE如何关闭代码规范 最近在学VUE,作为一个设计转前端的小白鼠. 总是能碰到各种各样奇葩的问题. 比如我碰到了 extra semicolon 百度了下说是这个原因造成的: 但是!!!!!关键点来 ...

  5. linux用户(组)及文件权限说明

    写在前面: 在liunx系统中一切都是文件(文件夹和外设是特殊的文件),如果有可能尽量使用文本文件,文本文件是人.机都能够理解的文件.linux的用户(组)和权限完美的解决了linux系统的安全问题. ...

  6. Python中if name == 'main':的作用

    一个python文件通常有两种使用方法, 第一是作为脚本直接执行. 第二是 import 到其它的 python 脚 本中被调用(模块重用)执行. 因此 if name == 'main': 的作用就 ...

  7. JMicro微服务Hello World

    概述 JMicro是本人开发的基于Java实现的微服务框架,前两天发布0.0.3正式版本,并已发布到maven中央仓库. 项目源码github:https://github.com/mynewworl ...

  8. Zabbix企业分布式监控工具

    前言:在工作中常常需要对服务器进行监控,但是要选择一款合适监控软件可不容易,今天介绍下zabbix这款监控软件 一.Zabbix介绍1.Zabbix是一个企业级的.开源的.分布式的监控套件2.Zabb ...

  9. RMAN-06172: no AUTOBACKUP found or specified handle is not a valid copy or piece

    问题描述:将备份集从一台主机拷贝到另外一台主机后,在通过RMAN将数据库恢复到同类机异机的时候,restore spfile一直报RMAN-06172: no AUTOBACKUP found or ...

  10. App元素定位三种方法

    来自博客: http://testingpai.com/article/1595507262082 以下方法操作前必须确保有手机设备连入电脑,检测是否有手机连入命令 adb devices 第一种:A ...