1.Query DSL概述
Domain Specific Language
领域专用语言
Elasticsearch提供了基于JSON的DSL来定义查询。
DSL由叶子查询子句和复合查询子句两种子句组成。
dsl是ElasticSearch的查询核心,复杂的查询操作都得是用dsl语句去操作
2.无查询条件
无查询条件是查询所有,默认是查询所有的,或者使用match_all表示所有
GET /es_db/_doc/_search
{
"query": {
"match_all": {}
}
}
3.有查询条件
3.1 叶子条件查询(单字段查询条件)
3.1.1 模糊匹配
模糊匹配主要是针对文本类型的字段,文本类型的字段会对内容进行分词,对查询时,也会对搜索条件进行分词,然后通过倒排索引查找到匹配的数据,模糊匹配主要通过match等参数来实现
- match : 通过match关键词模糊匹配条件内容
- prefix : 前缀匹配
- regexp : 通过正则表达式来匹配数据
match的复杂用法
match条件还支持以下参数:
- query : 指定匹配的值
- operator : 匹配条件类型
- and : 条件分词后都要匹配
- or : 条件分词后有一个匹配即可(默认)
- minmum_should_match : 指定最小匹配的数量
3.1.2 精确匹配
- term : 单个条件相等
- terms : 单个字段属于某个值数组内的值
- range : 字段属于某个范围内的值
- exists : 某个字段的值是否存在
- ids : 通过ID批量查询
3.2 组合条件查询(多条件查询)
组合条件查询是将叶子条件查询语句进行组合而形成的一个完整的查询条件
- bool : 各条件之间有and,or或not的关系
- must : 各个条件都必须满足,即各条件是and的关系
- should : 各个条件有一个满足即可,即各条件是or的关系
- must_not : 不满足所有条件,即各条件是not的关系
- filter : 不计算相关度评分,它不计算_score即相关度评分,效率更高
- constant_score : 不计算相关度评分
must/filter/shoud/must_not 等的子条件是通过 term/terms/range/ids/exists/match 等叶子条件为参数的
注:以上参数,当只有一个搜索条件时,must等对应的是一个对象,当是多个条件时,对应的是一个数组
3.3 连接查询(多文档合并查询)
- 父子文档查询:parent/child
- 嵌套文档查询: nested
3.4 DSL查询语言中存在两种:查询DSL(query DSL)和过滤DSL(filter DSL)
它们两个的区别如下图:
query DSL
在查询上下文中,查询会回答这个问题——“这个文档匹不匹配这个查询,它的相关度高么?”
如何验证匹配很好理解,如何计算相关度呢?ES中索引的数据都会存储一个_score分值,分值越高就代表越匹配。另外关于某个搜索的分值计算还是很复杂的,因此也需要一定的时间。
filter DSL
在过滤器上下文中,查询会回答这个问题——“这个文档匹不匹配?”
答案很简单,是或者不是。它不会去计算任何分值,也不会关心返回的排序问题,因此效率会高一点。
过滤上下文 是在使用filter参数时候的执行环境,比如在bool查询中使用must_not或者filter
另外,经常使用过滤器,ES会自动的缓存过滤器的内容,这对于查询来说,会提高很多性能。
一些过滤的情况:
3.5 Query方式查询:案例
根据名称精确查询姓名 term, term查询不会对字段进行分词查询,会采用精确匹配 ,term里面的信息就不进行分词操作了.
term
term: 这种查询和match在有些时候是等价的,比如我们查询单个的词hello,那么会和match查询结果一样,但是如果查询”hello world”,结果就相差很大,因为这个输入不会进行分词,就是说查询的时候,是查询字段分词结果中是否有”hello world”的字样,而不是查询字段中包含”hello world”的字样。当保存数据”hello world”时,elasticsearch会对字段内容进行分词,”hello world”会被分成hello和world,不存在”hello world”,因此这里的查询结果会为空。这也是term查询和match的区别。
注意: 采用term精确查询, 查询字段映射类型属于为keyword.
举例:
POST /es_db/_doc/_search
{
"query": {
"term": {
"name": "admin"
}
}
}
SQL: select * from student where name = 'admin'
1 term查询keyword字段。
term不会分词。而keyword字段也不分词。需要完全匹配才可。
hello world === hello world
hello world
2 term查询text字段。
因为text字段会分词,而term不分词,所以term查询的条件必须是text字段分词后的某一个。
根据备注信息模糊查询 match, match会根据该字段的分词器,进行分词查询
模糊查询的时候会用index索引的默认的分词器
match:模糊匹配,需要指定字段名,但是输入会进行分词,比如”hello world”会进行拆分为hello和world,然后匹配,如果字段中包含hello或者world,或者都包含的结果都会被查询出来,也就是说match是一个部分匹配的模糊查询。查询条件相对来说比较宽松。
举例:
POST /es_db/_doc/_search
{
"from": 0,
"size": 2,
"query": {
"match": {
"address": "广州"
}
}
}
SQL: select *from user where address like '%广州%' limit 0,2
1 match查询keyword字段
match会被分词,而keyword不会被分词,match的需要跟keyword的完全匹配可以。
2 match查询text字段
match分词,text也分词,只要match的分词结果和text的分词结果有相同的就匹配。
多字段模糊匹配查询与精准查询 multi_match
模糊查询
POST /es_db/_doc/_search
{
"query": {
"multi_match": {
"query": "张三",
"fields": [
"address",
"name"
]
}
}
}
SQL: select * from student where name like '%张三%' or address like '%张三%'
query_string:和match类似,但是match需要指定字段名,query_string是在所有字段中搜索,范围更广泛。
和 match有点像.但是还是有区别的,match需要声明字段,而query_string不需要声明字段,只要符合要求就查询出来.
广州 AND 长沙 代表 既要有广州,又要有 长沙
广州 OR 长沙 代表 有广州或者有长沙
另外 query_string 可以分词查询,”query”:”广州公园 AND 长沙” 这样写,ElasticSearch可能会把广州公园进行拆开分词操作.
POST /es_db/_doc/_search
{
"query": {
"query_string": {
"query": "广州 OR 长沙"
}
}
}
指定字段条件查询 query_string , 含 AND 与 OR 条件
query_string 查询的时候 只是匹配fields声明的字段信息
下面的意思是 查询name和address中包含admin或者长沙的数据
POST /es_db/_doc/_search
{
"query":{
"query_string":{
"query":"admin OR 长沙",
"fields":["name","address"]
}
}
}
注:json请求字符串中部分字段的含义
range:范围关键字
gte 大于等于
lte 小于等于
gt 大于
lt 小于
now 当前时间
# 查询年龄在25~28的数据
POST /es_db/_doc/_search
{
"query": {
"range": {
"age": {
"gte": 25,
"lte": 28
}
}
}
}
SQL: select * from user where age between 25 and 28
POST /es_db/_doc/_search
{
"query": {
"range": {
"age": {
"gte": 25,
"lte": 28
}
}
},
"from": 0,
"size": 2,
"_source": [ # 只显示这些字段
"name",
"age",
"book"
],
"sort": { # 排序字段
"age": "desc"
}
}
3.6 Filter过滤器方式查询
它的查询不会计算相关性分值,也不会对结果进行排序, 因此效率会高一点,查询的结果可以被缓存。
Filter Context 对数据进行过滤
POST /es_db/_doc/_search
{
"query": {
"bool": {
"filter": {
"term": {
"age": 25
}
}
}
}
}