大家好,我是老坛。

更多优质文章资源请关注同名公众号:老坛聊开发

Elasticsearch是一个分布式的RESTful 风格的搜索和数据分析引擎,它使用方便,查询速度快,因此也被越来越多的开发人员使用。

本篇文章主要带大家过一下ES的基础查询语法,但对于其背后的原理和查询机理我不会做太多介绍,好了我们开始正题。

目录

1. ES分词器

2. ES查询

2.1 match查询

2.2 match_phrase查询

2.3 multi_match查询

2.4 term查询

2.5 terms查询

2.6 fuzzy查询

2.7 range查询

2.8 bool查询

2.9 排序和分页

3. 总结


1. ES分词器

在学习查询语法之前有必要带大家了解一下ES的分词器。因为这是题主认为ES搜索引擎最大的特点了,它查询速度之所以这么快也和这个有很大关系。但更重要的是,如果我们不了解ES会对你存储的索引文本或者查询query进行分词,后面的语法你将很难理解。

对于我们存入ES索引(Index)中的各个字段(Term),ES内部都会有一个分词器对其进行分词,然后将这个分词结果存储起来,方便你未来的查询使用,这个分词器我们也可以直接很方便的调用,只要访问其_analyze即可:

POST http://ip:prot/_analyze
{"analyzer": "standard","text": "This is a test doc"
}

这里需要指定一个分词器,ES默认的分词器是standard,不过只支持英文分词,如果你用它来对中文进行分词的话会直接按字拆分,有一些中文分词器可以下载使用,像ik或者jieba之类的,这里便不去介绍如何安装了,感兴趣的可以查阅相关文章。

回到正题,我们用上述的分词请求返回的结果如下:

{"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},{"token": "doc","start_offset": 15,"end_offset": 18,"type": "<ALPHANUM>","position": 4}]
}

可以看到我们的句子就被分词器这样做好了分词,还有偏移量之类的信息。

这里只是带大家看一下ES是如何做到分词的,我们平时查询的话自己是用不到分词的,这些分词都是在保存索引时ES自动分好存储起来的。

2. ES查询

下面介绍一下ES常用的几种查询(题主只介绍常用的,一些复杂用法可能不会都介绍全,大家在实际学习和工作中遇到了再去官方文档中查就好啦)。

更多优质文章资源请关注同名公众号:老坛聊开发

2.1 match查询

ES的查询有一个很大的特点就是分词。所以大家在使用ES的过程中脑子要始终有这么一个意识,你要查找的text是通过分词器分过词的,所以你去匹配的实际上是一个个被分词的片段。而你搜索的query也有可能会被分词,match就是一种会将你搜索的query进行分词的查询方法。我们结合例子来看!

比如我们要查询的索引结构如下:

{"_index": "textbook","_id": "kIwXeYQB8iTYJNkI986Y","_source": {"bookName": "This is a test doc","author": "老坛","num": 20}
}

_index代表索引名称,_id代表该条数据唯一id,_source代表该条数据具体的结构。

这里我们通过bookName字段来查询。

输入query语句如下:

GET http://ip:prot/textbook/_search
{"query": {"match": {"bookName":"test"}}
}

该条语句代表用match方式搜索索引为textbook中bookName可以匹配到test的语句。因为:

"bookName": "This is a test doc"

原文被分词器分词后包含test这个词语,所以可以正常被匹配出来。

这个例子比较简单,我们换个复杂一点的例子:

GET http://ip:prot/textbook/_search
{"query": {"match": {"bookName":"my test"}}
}

大家认为这个能否被匹配出来呢?

原文中根本就没有my这个词语,那怎么被匹配出来?但实际上是可以匹配出来的。

原因是match查询里,会对你查询的query也进行分词,也就是会将你的"my test"进行分词,得到my与test两个词语,然后用这两个词语分别去匹配文本,发现虽然my匹配不到,但是test可以匹配到,所以依然可以查出来。这个和我们传统的搜索方式确实存在差异,大家要注意。

那这种搜索方式存在的价值是什么呢?其实还有蛮大用处的。比如我们的ES库存储的是很多的英文好词好句,然后用户想提高自己的英文写作,因此想搜索出一些比较好的表达加在自己的文章中,那这个时候对于用户来讲,严格的匹配方式大概率什么都搜不到,但是像match这样的搜索方式便非常合适。例如有个好句是这样的:

If at first you don't succeed, try again.

然后用户用下面的方式搜索:

If you don't success

用match就可以很好的匹配出来。

2.2 match_phrase查询

既然match的限制比较小,那如果我们需要这个限制更强一点用什么方式呢?match_phrase便是一个比较不错的选择。match_phrase和match一样也是会对你的搜索query进行分词,但是,不同的是它不是匹配到某一处分词的结果就算是匹配成功了,而是需要query中所有的词都匹配到,而且相对顺序还要一致,而且默认还是连续的,如此一来,限制就更多了。我们还是举个例子。比如还是刚刚的索引数据:

{"_index": "textbook","_id": "kIwXeYQB8iTYJNkI986Y","_source": {"bookName": "This is a test doc","author": "老坛","num": 20}
}

如果我们还用刚刚的方式搜索:

GET http://ip:prot/textbook/_search
{"query": {"match_phrase": {"bookName":"my test"}}
}

这次是匹配不到结果的。那么怎样才能匹配到结果呢?只能是搜索原文中的连续字串:

GET http://ip:prot/textbook/_search
{"query": {"match_phrase": {"bookName":"is a test"}}
}

这样是可以匹配到结果的。但是如此一来限制可能太大了一点,所以官方还给了一个核心餐宿可以调整搜索的严格程度,这个参数叫slop,我们举个例子:

GET http://ip:prot/textbook/_search
{"query": {"match_phrase": {"bookName":{"query":"is test","slop":1}}}
}

比如我们将slop置为1,然后搜索"is test",虽然is test中间省略了一个词语"a",但是在slop为1的情况下是可以容忍你中间省略一个词语的,也可以搜索出来结果。以此类推,slop为2就可以省略两个词语了。大家可以根据自己的实际情况进行调整。

另外我们可以发现,如果在搜索时添加了辅助参数(比如slop)我们搜索格式的层级要往下扩展一层,之前的

"bookName":"my test"

要改为:

"bookName":{"query":"is test","slop":1
}

我们注意一下就好了。

2.3 multi_match查询

有了前面的基础,multi_match比较好理解。实际上就是可以从多个字段中去寻找我们要查找的query:

GET http://ip:prot/textbook/_search
{"query": {"multi_match": {"query" : "老坛","fields" : ["bookName", "author"]}}
}

比如这里我们是从bookName和author两个字段里去寻找老坛,虽然bookName没有,但是author可以匹配到,那也可以找到数据。所以本质上就是对bookName和author分别做了一次match:

{"_index": "textbook","_id": "kIwXeYQB8iTYJNkI986Y","_source": {"bookName": "This is a test doc","author": "老坛","num": 20}
}

2.4 term查询

term查询也是比较常用的一种查询方式,它和match的唯一区别就是match需要对query进行分词,而term是不会进行分词的,它会直接拿query整体和原文进行匹配。所以不理解的小伙伴使用起来可能会非常奇怪:

GET http://ip:prot/textbook/_search
{"query": {"term": {"bookName": "This is a test doc"}}
}

当我们用这种方式进行搜索时,明明要搜索的和被搜索的文本一模一样,确就是搜不出来。这就是因为我们去搜的实际上并不是原文本身,而是被分词的原文,在原文被分好的每一个词语里,没有一个词语是:"This is a test doc",那自然是什么都搜不到了。所以在这种情况下就只能用某一个词进行搜索才可以搜到:

GET http://ip:prot/textbook/_search
{"query": {"term": {"bookName": "This"}}
}

2.5 terms查询

terms查询事实上就是多个term查询取一个交集,也就是要满足多个term查询条件匹配出来的结果才可以查到,所以是比单纯的term条件更为严格了:

GET http://ip:prot/textbook/_search
{"query": {"terms": {"bookName": ["This", "is"]}}
}

比如这个例子,是要求原文中既有This这个词,又有is这个词才可以被查到,那按照这个规则我们是可以匹配到数据的:

{"_index": "textbook","_id": "kIwXeYQB8iTYJNkI986Y","_source": {"bookName": "This is a test doc","author": "老坛","num": 20}
}

但是如果改成了一个不存在的词便匹配不到了:

GET http://ip:prot/textbook/_search
{"query": {"terms": {"bookName": ["This", "my"]}}
}

2.6 fuzzy查询

fuzzy是ES里面的模糊搜索,它可以借助term查询来进行理解。fuzzy和term一样,也不会将query进行分词,但是不同的是它在进行匹配时可以容忍你的词语拼写有错误,至于容忍度如何,是根据参数fuzziness决定的。fuzziness默认是2,也就是在默认情况下,fuzzy查询容忍你有两个字符及以下的拼写错误。即如果你要匹配的词语为test,但是你的query是text,那也可以匹配到。这里无论是错写多写还是少写都是计算在内的。我们同样还是举例说明。

对于索引数据:

{"_index": "textbook","_id": "kIwXeYQB8iTYJNkI986Y","_source": {"bookName": "This is a test doc","author": "老坛","num": 20}
}

如果查询语句为:

GET http://ip:prot/textbook/_search
{"query": {"fuzzy": {"bookName":"text"}}
}

这时肯定是用text来匹配原文中的每一个词,发现text和test最为接近,但是有一个字符的差异,在默认fuzziness为2的情况下,依然可以匹配出来。

当然这个fuzziness是可以调的,比如:

GET http://ip:prot/textbook/_search
{"query": {"fuzzy": {"bookName":{"value":"texts","fuzziness":1}}}
}

在容忍度为1的情况下,如果你想查texts就查不到结果了。

2.7 range查询

range查询时对于某一个数值字段的大小范围查询,比如我这里特意所加的nums字段就是这个时候派上用场的。range的语法设计到了一些关键字:

  1. gte:大于等于
  2. gt:大于
  3. lt:小于
  4. lte:小于等于
GET http://ip:prot/textbook/_search
{ "query": {"range": { "num": { "gte":20, "lt":30 } }}
}

比如这样的条件就是去查找字段num大于等于20小于30的数据

那我们的数据便可以被查询到:

{"_index": "textbook","_id": "kIwXeYQB8iTYJNkI986Y","_source": {"bookName": "This is a test doc","author": "老坛","num": 20}
}

2.8 bool查询

bool查询是上面查询的一个综合,它可以用多个上面的查询去组合出一个大的查询语句,它也有一些关键字:

更多优质文章资源请关注同名公众号:老坛聊开发

  1. must:代表且的关系,也就是必须要满足该条件
  2. should:代表或的关系,代表符合该条件就可以被查出来
  3. must_not:代表非的关系,也就是要求不能是符合该条件的数据才能被查出来

例如有这样一个查询:

GET http://ip:prot/textbook/_search
{"query":{"bool":{"must":{"match":{"bookName":"老坛"}},"should":{"term":{"author":"老坛"},"range":{"num":{"gt":20}},}}}
}

这里就要求must里面的match是必须要符合的,但是should里面的两个条件就可以符合一条即可。

2.9 排序和分页

排序和分页也是建立在上述的那些搜索之上的。排序和分页的条件是和query平级去写的,我们一个一个来看。先举个例子:

GET http://ip:prot/textbook/_search
{"query":{"match":{"bookName":"老坛"}},"from":0,"size":100,"sort":{"num":{"order":"desc"}}
}

这里关于分页的语句是:

"from":0,
"size":100,

它代表的意思是按照页容量为100进行分页,取第一页​。

关于排序的语句是:

"sort":{"num":{"order":"desc"}
}

它需要指定一个字段,然后根据这个字段进行升序或降序。这里我们根据num来进行降序排序,如果想升序就把order的值改为asc就好了。

3. 总结

那么到这里ES的基础语法就给大家介绍完了,如果还想了解更多可以去阅读官方的相关文档。看了这一篇,你对于ES的一些常用操作基本就可以满足了。如果大家是在Java项目里使用ES的话也可以看看老坛写的Java操作ES的API文档。感谢大家的支持!

【ES使用】Java API操作ES宝典(7.x版本及其以下)https://blog.csdn.net/qq_34263207/article/details/127793370【ES使用】Java API操作ES宝典(8.x版本)https://blog.csdn.net/qq_34263207/article/details/127847033

【ES知识】ES基础查询语法一览相关推荐

  1. solr 基础查询语法

    等于 = #表示 key = value key:value示例: id:a6c1980ced984ff5b172eb685e108ab8* AND price:22.75 不等于 != #在 key ...

  2. mysql基础查询语法

  3. SQL语法之基础查询(进阶1)and条件查询(进阶2)

    SQL语法体系学习笔记 SQL语法之基础查询(进阶1)and条件查询(进阶2) SQL语法之排序查询(进阶3)and常见函数(进阶4) SQL语法之分组函数,分组查询(进阶5)and连接查询(sql9 ...

  4. ElasticSearch 高级查询语法

    ElasticSearch 高级查询语法Query DSL ES倒排索引 ES高级查询Query DSL 查询所有 match_all 分页查询form 深分页查询Scroll 指定字段排序sort ...

  5. 查询去重_【Freya的MySQL课堂】DQL基础查询

    MYSQL 基础查询 各位小伙伴们晚上好,今天是10月22号. 我是你们的Freya. 今天我们开始学习MySQL中的DQL语言. Do Not Stop Learning 我 的 小 课 堂 我爱学 ...

  6. SQL语言之DQL语言学习(一) 基础查询

    DQL(data query language)数据查询语言select DQL (数据查询语言) 用于查询数据库的数据 主要命令 SELECT 基础查询 语法 select 查询列表 from 表名 ...

  7. 一、MySQL查询学习笔记(基础查询、条件查询、排序查询、常见函数、分组查询 详解)

    DQL语言的学习 一.基础查询 语法: **SELECT 要查询的东西 [FROM 表名];**类似于Java中 :System.out.println(要打印的东西); 特点: ①通过select查 ...

  8. 7.基础查询(select from)

    进阶一:基础查询 /* 语法:select 查询列表 from 表名; 特点: 1.查询列表可以是:表中的字段,常量值,表达式,函数 2.查询结果是一个虚拟的表格 */ myemployees表::对 ...

  9. mysql查询个人信息查询_MySQL:基础查询

    MySql:基础查询 语法: SELECT 要查询的东西 [FROM 表名]; 类似于Java中 :System.out.println(要打印的东西); 特点: ①通过select查询完的结果 ,是 ...

最新文章

  1. C指针6:指针变量作为函数参数
  2. Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)...
  3. cassandra java driver
  4. 数据库系统概念总结:第十四章 事务
  5. cannot access xxx的解决办法
  6. oracle分区表学习及应用
  7. linux bash profile bash_profile 小结
  8. oracle服务端导出/导入方式expdp/impdp
  9. 国家气象数据中心网站
  10. 简单工厂、工厂方法、抽象工厂区别
  11. 简述no less than和not less than区别
  12. php168+v9+下载,PHPCMS-PHPCMS V9-PHPCMS下载 V9.1正式版-完美下载
  13. 如何设计一个电商平台积分兑换系统?
  14. SAP系统用户账号类型介绍
  15. rdt 可靠数据传输协议
  16. 网站建设制作需要多少钱呢?费用是多少?
  17. MATLAB对ply文件格式的读取和显示
  18. PHP文件怎么改tne,修改 · thinkphp6文档 · 看云
  19. 工具-安装redis和安装redis客户端
  20. stm32—霍尔传感器的初步使用

热门文章

  1. kali的网络设置及三种网络模式
  2. Android - View - ViewPager
  3. EcIo,EcNo,RSSI,RSCP等常见参数详解
  4. WPF 用户控件和 WPF自定义控件区别
  5. 一个关于xgen开发导入的问题,但其实我觉得更重要的是过程中发生的事情。
  6. 2019阿里云峰会·北京 | 十年再出发
  7. 【分治】大整数乘法(C++)
  8. 【3D建模制作技巧分享】zbrush中如何卡硬边?
  9. BitBlt C++中BitBlt如何使用详解
  10. SSM和Springboot框架比较的优缺点