我们在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参数指定了要返回多少文档,因此,通过利用fromsize,我们可以方便的实现分页操作。

_source

跟其他的数据库操作一样,有的时候我们并不需要返回一个文档的所有字段,返回部分字段,可以极大的减少数据量的传输,比如,对于customer中的文档,我们只希望返回fristnamelastname两个字段,这个时候就可以使用_source关键字了:

curl -XGET 'localhost:9200/customer/_search?pretty' -H 'Content-Type: application/json' -d'
{"query": { "match_all": {} },"_source": ["firstname", "lastname"]
}
'

目前为止,我们已经介绍了关于查询的几个关键字,在继续往下进行之前,先来总结一下:

  1. query:指定查询的条件
  2. match_all:匹配所有文档
  3. sort:对结果进行排序
  4. from:查询结果起始位置,从0开始
  5. size:查询结果大小
  6. _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中,我们也可以单独的使用这种类型的查询,布尔查询的关键字是boolbool查询将许多个小的查询利用一定的布尔逻辑综合成一个较大的查询。比如,上面查询既包含朝阳区又包含和平街的语句就可以利用bool改写成下面这样:

curl -XGET 'localhost:9200/customer/_search?pretty' -H 'Content-Type: application/json' -d'
{"query": {"bool": {"must": [{ "match": { "address": "朝阳区" } },{ "match": { "address": "和平街" } }]}}
}
'

改成bool查询后,逻辑变得更清晰了。同时,我们看到了一个新的关键字must,在bool查询中,并不是用orand来声明逻辑关系的,must表明所有的查询条件都返回True的时候才能匹配,作为对比,用should来表明or的逻辑关系。

should的行为并不像我们通常理解的那样:只要有一个条件返回True就匹配成功。事实上,我们在使用bool的时候,还会涉及到另外一个参数:minimum_should_match,如果不指定这个参数,则默认当所有条件都返回False的时候,也会匹配成功。

除此之外,在一个bool查询中还可以同时指定mustshouldmust_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查询,它除了支持mustshouldmust_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 - 高级查询功能相关推荐

  1. MySQL简单快速入门 (三)高级查询——JEPLUS软件快速开发平台

    03.SQL高级查询_分组: 1).需求:一条查询,查询出每种商品的最高价格 2).分组的命令:group by 分组字段 3).实现上例: select category_id,max(price) ...

  2. 【MySQL快速入门】高级查询:计算函数分组计算

    使用聚合函数汇总数据: SQL提供统计函数: count([shift+8]):统计表中元组个数 count([distinct]<列名>):统计本列列值个数 sum(<列名> ...

  3. 【Golang 快速入门】高级语法:反射 + 并发

    Golang 快速入门 Golang 进阶 反射 变量内置 Pair 结构 reflect 结构体标签 并发知识 基础知识 早期调度器的处理 GMP 模型 调度器的设计策略 并发编程 goroutin ...

  4. ELK之ElasticSearch快速入门

    ElasticSearch快速入门 一.简介 二.下载 三.启动 4.基本概念 5. 一.简介 官网:https://www.elastic.co/ ElasticSearch是Elastic Sta ...

  5. 尚硅谷-SpringBoot高级-检索-Elasticsearch快速入门

    前面我们安装好了ElasticSearch,我以后就简称他为ES,而一些人还不知道基本的使用,那我们接下来做一个快速入门,了解一下他的使用方法,以及一些基本概念,方便我们后来整合,那么要学习ES最好的 ...

  6. ElasticSearch快速入门

    官网地址(https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html)而且是中文的 Elastic的快速入门 1.基础 ...

  7. Go Elasticsearch 快速入门

    文章目录 1.入门简介 2.基本概念 3.客户端库 4.创建客户端 5.index 增删改查 6.增加 7.删除 8.修改 9.查询 10.小结 参考文献 1.入门简介 Elasticsearch 简 ...

  8. ElasticSearch快速入门实战

    一.ElasticSearch简介 1.简介 创始人是Shay Banon(谢巴农),它是java开发,是凯源的企业级搜索引擎,能够实现实时搜索,特点是稳定.可靠.快速,并且安装使用方便.(内置JDK ...

  9. ElasticSearch快速入门详解(亲测好用,强烈推荐收藏)

    3.快速入门 接下来快速看下elasticsearch的使用 3.1.概念 Elasticsearch虽然是一种NoSql库,但最终的目的是存储数据.检索数据.因此很多概念与MySQL类似的. ES中 ...

最新文章

  1. echarts中toolbox位置_基于QGIS中的LSMS(大规模均值漂移)分割算法
  2. HashMap构造函数有哪些
  3. MyBatis mapper代理方式
  4. Java易混小知识——equals方法和==的区别
  5. 考研数学三部曲之大话线性代数
  6. linux snap文件夹,SNAP 文件扩展名: 它是什么以及如何打开它?
  7. SQL Server数据挖掘简介
  8. Linux 的文件软链接如何删除
  9. 使用永洪BI工具开发扫雷游戏
  10. 如何用命令行去修改视频文件格式
  11. DC入门(二)综合脚本
  12. Exp8 Web基础 20154328 常城
  13. 关于迪文屏T5L使用C51编程
  14. FPGA的速度等级(speed grade)
  15. sql面试题——手写sql练习案例(一)
  16. 图像识别毕业设计 人脸识别与疲劳检测系统设计与实现 - python opencv
  17. 海思HI3516移植使用AP6181 BCM43362
  18. IDEA使用手记——IDEA主菜单恢复
  19. 【5G系列】MICO学习总结(3)
  20. java根节点到叶子节点_二叉树根节点到叶子节点的所有路径和

热门文章

  1. python云顶之翼
  2. Java反射和动态代理
  3. Python词频统计之密信约定进攻时间
  4. WPF RichTextBox设置行间距
  5. 卸载/关闭/使无效intel dptf (Intel(R) Dynamic Platform and Thermal Framework Generic Participant)
  6. 微信公众号测试号本地服务的搭建——Java
  7. iOS备忘录之Xcode折叠代码
  8. c语言陆黎明答案,清华大学出版社-图书详情-《C语言程序设计》
  9. 瞬间解除电脑开机密码
  10. 程序员异地恋如何处理抓住对方的心