Elasticsearch快速入门2 - 高级查询功能
我们在Elasticsearch快速入门1中详细介绍了ES的安装、基本概念和一些基本的REST Api
请求,在这篇入门(2)中,我们继续介绍ES的高级查询功能。
为了说明ES强大的搜索功能,我们还以上篇文章中的customer索引为例,但对其中的文档字段进行了一定的补充,补充后一个文档的内容大致如下所示:
{"firstname": "zhang","lastname": "san","age": 29,"gender": "F","address": "某某区某某街某某小区某号楼某单元某零几","email": "san.zhang@qq.com","city": "北京"
}
在ES中有两种方式可以进行高级查询,一种是通过在REST request URI
中传递参数,另一种是通过REST request body
来传递查询参数。因为第二种方式更富有表现力、不受URI长度的限制并且使用了更加易读的JSON格式来表示,因此实际应用中多数以request body
的形式来查询,我们这里也不再对第一种方式进行过多的介绍。
如果想通过
REST API
来使用查询功能,则必须要在URI
的最后添加_search
关键字,并且不需要再指定类型(type)。
match_all
首先来看下怎么查询customer索引下的所有文档:
curl -XGET 'localhost:9200/customer/_search?pretty' -H 'Content-Type: application/json' -d'
{"query": { "match_all": {} }
}
'
query
关键字说明了我们希望进行的是查询操作,它的值就是要查询的条件。上面的请求返回的数据我们摘录一部分内容,如下所示:
{"took" : 4,"timed_out" : false,"_shards" : {"total" : 5,"successful" : 5,"failed" : 0},"hits" : {"total" : 3,"max_score" : 1.0,"hits" : []}
}
其中,每个字段的含义是:
- took – ES执行查询操作用时,单位为milliseconds
- timed_out – 查询是否超时
- _shards – 查询了几个分片,每个分配查询的结果是什么
- hits – 查询的结果
- hits.total – 匹配我们搜索条件的文档数量
- hits.hits – 查询结果的数组,默认是取前10个文档
- hits.sort – 对结果进行排序的字段,如果没有排序这个字段为空
- hits._score 和 max_score – 文档与指定查询的相关性,越高说明相关性越大
sort
如果我们想对结果进行排序,可以使用sort
关键字:
curl -XGET 'localhost:9200/customer/_search?pretty' -H 'Content-Type: application/json' -d'
{"query": { "match_all": {} },"sort": [{ "account_number": "asc" }]
}
'
因为可以根据多个字段进行排序,因此sort
关键字对应的是一个数组,允许我们指定多个排序策略。
size、from
我们在介绍返回结果字段含义的时候说过,默认是取前10个文档,如果想修改这个值可以指定size
参数,比如只取一个文档:
curl -XGET 'localhost:9200/customer/_search?pretty' -H 'Content-Type: application/json' -d'
{"query": { "match_all": {} },"size": 1
}
'
默认情况下,上面的请求返回的是从第0个文档算起的,同样,我们也可以修改这个值,比如取第11个到第20个文档,就要指定另外一个值from
:
curl -XGET 'localhost:9200/customer/_search?pretty' -H 'Content-Type: application/json' -d'
{"query": { "match_all": {} },"from": 10,"size": 10
}
'
有一点需要强调的是,from
这个参数是从0开始的,它表明了希望从哪里开始截取数据,size
参数指定了要返回多少文档,因此,通过利用from
和size
,我们可以方便的实现分页操作。
_source
跟其他的数据库操作一样,有的时候我们并不需要返回一个文档的所有字段,返回部分字段,可以极大的减少数据量的传输,比如,对于customer中的文档,我们只希望返回fristname
和lastname
两个字段,这个时候就可以使用_source
关键字了:
curl -XGET 'localhost:9200/customer/_search?pretty' -H 'Content-Type: application/json' -d'
{"query": { "match_all": {} },"_source": ["firstname", "lastname"]
}
'
目前为止,我们已经介绍了关于查询的几个关键字,在继续往下进行之前,先来总结一下:
query
:指定查询的条件match_all
:匹配所有文档sort
:对结果进行排序from
:查询结果起始位置,从0开始size
:查询结果大小_source
:指定返回的字段
match
match_all
查询可以匹配所有的文档,但大部分时候这个查询是没啥意义的,如果只需要查询所有文档,就没有非用ES不可的理由了。当我们需要根据某个字段进行查找,这个时候match
就派上用场了,先来看一下用法:
curl -XGET 'localhost:9200/customer/_search?pretty' -H 'Content-Type: application/json' -d'
{"query": { "match": { "age": 20 } }
}
'
上面的请求会查询年龄为20的文档。除了数字类型,match
还可以接受文本和日期类型的查询条件,看下一个例子:
curl -XGET 'localhost:9200/customer/_search?pretty' -H 'Content-Type: application/json' -d'
{"query": { "match": { "address": "朝阳区和平街" } }
}
'
在这个例子中,我们的查询条件是一个字符串,ES会返回给我们什么样的数据呢?在其他数据库系统中,只有address字段的内容跟查询条件完全一致才能被匹配,而在ES中则大不同。
ES首先会对朝阳区和平街
进行分析,假如分析的结果是将这个字符串拆分成了朝阳区
和和平街
,然后,根据倒排索引,会找到所有包含朝阳区
或者包含和平街
的文档。
如何对查询文本进行分析,并不是一成不变的,我们可以指定分析器,来告诉ES怎么对文本进行拆分,上面的这种拆分需要用到一个中文的分词器叫做
ik_smart
,ES默认是不支持中文分词的,需要安装第三方的工具。
这里之所以说是或者包含
,是因为我们没有指定match
的行为,通过operator
关键字,我们可以指定是or
还是and
。比如我们希望找到既包含朝阳区
又包含和平街
的文档,就可以改写上面的语句如下:
curl -XGET 'localhost:9200/customer/_search?pretty' -H 'Content-Type: application/json' -d'
{"query": {"match" : {"address" : {"query" : "朝阳区和平街","operator" : "and"}}}
}
'
bool
之所以在使用match
的时候可以指定operator
,是因为match
其实是一种布尔类型的查询。在ES中,我们也可以单独的使用这种类型的查询,布尔查询的关键字是bool
,bool
查询将许多个小的查询利用一定的布尔逻辑综合成一个较大的查询。比如,上面查询既包含朝阳区
又包含和平街
的语句就可以利用bool
改写成下面这样:
curl -XGET 'localhost:9200/customer/_search?pretty' -H 'Content-Type: application/json' -d'
{"query": {"bool": {"must": [{ "match": { "address": "朝阳区" } },{ "match": { "address": "和平街" } }]}}
}
'
改成bool
查询后,逻辑变得更清晰了。同时,我们看到了一个新的关键字must
,在bool
查询中,并不是用or
、and
来声明逻辑关系的,must
表明所有的查询条件都返回True的时候才能匹配,作为对比,用should
来表明or
的逻辑关系。
should
的行为并不像我们通常理解的那样:只要有一个条件返回True就匹配成功。事实上,我们在使用bool
的时候,还会涉及到另外一个参数:minimum_should_match
,如果不指定这个参数,则默认当所有条件都返回False的时候,也会匹配成功。
除此之外,在一个bool
查询中还可以同时指定must
、should
、must_not
。还是以上面的例子说明,除了希望address
至少包含朝阳区
或和平街
外,还希望age
等于20:
curl -XGET 'localhost:9200/customer/_search?pretty' -H 'Content-Type: application/json' -d'
{"query": {"bool": {"should": [{ "match": { "address": "朝阳区" } },{ "match": { "address": "和平街" } }],"must": {"match": {"age": 20}},"minimum_should_match": 1 }}
}
'
term
除了match
查询外,还有一个term
查询,term
查询跟match
查询唯一不同的一点是:term
查询不会对查询文本进行分析,而是直接去倒排索引中去看都有哪些文档包含要查询的条件;match
是首先对要查询的文本进行分析,划分为多个子文本,然后将一个大查询拆分成多个小查询,最后进行汇总处理。因此,如果match
查询不能对查询文本进行再划分,那么它与term
查询的效果是一样的。
还是上面的查询,将match
换成term
:
curl -XGET 'localhost:9200/customer/_search?pretty' -H 'Content-Type: application/json' -d'
{"query": { "term": { "address": "朝阳区和平街" } }
}
'
这个查询的含义就变成了查询在address中包含朝阳区和平街
这个字符串的文档。
query与filter
最后,我们来说下filter
,对于很多初学者来说,有的时候很难区分query
查询和filter
查询,尤其是遇到两种方法都能正确得到数据的情况下,更是难决断。所以,在这节我们来看下两者的区别。
首先来说query
查询,对于query
语句,它要回答的是:某个文档跟查询语句的匹配程度如何?除了决定一个文档是否匹配查询语句外,还要计算一个_score
值,这个值就代表了文档的相关性,值越大说明相关性越高。但是,对于这个值,我们大多数时候并不关心,如果不再计算这个值势必会在一定程度上提高ES查询的效率,因此,引入了filter
查询。
对于filter
语句,只考虑某个文档是否匹配,也就是Yes or No的问题,并不计算相关性,这种情况下可以类比于一般数据库的select语句。filter
另外一个跟query
不同的地方是,ES会对经常使用的filter进行缓存,以此来提供查询效率,而query
不会使用缓存。
如此一来,我们的结论就是,在构造查询语句的时候,能使用filter
的地方绝不使用query
。
我们在上面的内容中介绍了bool
查询,它除了支持must
、should
、must_not
外,还可以支持filter
语句,例如:
curl -XGET 'localhost:9200/customer/_search?pretty' -H 'Content-Type: application/json' -d'
{"query": {"bool": {"must": { "match_all": {} },"filter": {"range": {"age": {"gte": 20, "lte": 30}}}}}
}
'
上面的语句查询了所有年龄在20到30之间的人,它包含一个match_all
语句和一个range
语句,其中range
是放在filter
中的,当然如果不使用filter
也是可以的,像下面这样:
curl -XGET 'localhost:9200/customer/_search?pretty' -H 'Content-Type: application/json' -d'
{"query": {"bool": {"must": { "range": {"age": {"gte": 20, "lte": 30}} }}}
}
'
不过,还是那句话,能使用filter
的地方绝不使用query
。
到这里,查询语句的介绍就到这里,在入门(3)中,会继续介绍ES中的几种特殊的数据类型:列表类型和嵌套类型。
完!
Elasticsearch快速入门2 - 高级查询功能相关推荐
- MySQL简单快速入门 (三)高级查询——JEPLUS软件快速开发平台
03.SQL高级查询_分组: 1).需求:一条查询,查询出每种商品的最高价格 2).分组的命令:group by 分组字段 3).实现上例: select category_id,max(price) ...
- 【MySQL快速入门】高级查询:计算函数分组计算
使用聚合函数汇总数据: SQL提供统计函数: count([shift+8]):统计表中元组个数 count([distinct]<列名>):统计本列列值个数 sum(<列名> ...
- 【Golang 快速入门】高级语法:反射 + 并发
Golang 快速入门 Golang 进阶 反射 变量内置 Pair 结构 reflect 结构体标签 并发知识 基础知识 早期调度器的处理 GMP 模型 调度器的设计策略 并发编程 goroutin ...
- ELK之ElasticSearch快速入门
ElasticSearch快速入门 一.简介 二.下载 三.启动 4.基本概念 5. 一.简介 官网:https://www.elastic.co/ ElasticSearch是Elastic Sta ...
- 尚硅谷-SpringBoot高级-检索-Elasticsearch快速入门
前面我们安装好了ElasticSearch,我以后就简称他为ES,而一些人还不知道基本的使用,那我们接下来做一个快速入门,了解一下他的使用方法,以及一些基本概念,方便我们后来整合,那么要学习ES最好的 ...
- ElasticSearch快速入门
官网地址(https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html)而且是中文的 Elastic的快速入门 1.基础 ...
- Go Elasticsearch 快速入门
文章目录 1.入门简介 2.基本概念 3.客户端库 4.创建客户端 5.index 增删改查 6.增加 7.删除 8.修改 9.查询 10.小结 参考文献 1.入门简介 Elasticsearch 简 ...
- ElasticSearch快速入门实战
一.ElasticSearch简介 1.简介 创始人是Shay Banon(谢巴农),它是java开发,是凯源的企业级搜索引擎,能够实现实时搜索,特点是稳定.可靠.快速,并且安装使用方便.(内置JDK ...
- ElasticSearch快速入门详解(亲测好用,强烈推荐收藏)
3.快速入门 接下来快速看下elasticsearch的使用 3.1.概念 Elasticsearch虽然是一种NoSql库,但最终的目的是存储数据.检索数据.因此很多概念与MySQL类似的. ES中 ...
最新文章
- echarts中toolbox位置_基于QGIS中的LSMS(大规模均值漂移)分割算法
- HashMap构造函数有哪些
- MyBatis mapper代理方式
- Java易混小知识——equals方法和==的区别
- 考研数学三部曲之大话线性代数
- linux snap文件夹,SNAP 文件扩展名: 它是什么以及如何打开它?
- SQL Server数据挖掘简介
- Linux 的文件软链接如何删除
- 使用永洪BI工具开发扫雷游戏
- 如何用命令行去修改视频文件格式
- DC入门(二)综合脚本
- Exp8 Web基础 20154328 常城
- 关于迪文屏T5L使用C51编程
- FPGA的速度等级(speed grade)
- sql面试题——手写sql练习案例(一)
- 图像识别毕业设计 人脸识别与疲劳检测系统设计与实现 - python opencv
- 海思HI3516移植使用AP6181 BCM43362
- IDEA使用手记——IDEA主菜单恢复
- 【5G系列】MICO学习总结(3)
- java根节点到叶子节点_二叉树根节点到叶子节点的所有路径和