参考:

https://es.xiaoleilu.com/054_Query_DSL/55_Request_body_search.html

请求体查询

GET /_search
{} 分页
GET /_search
{
"from": 30,
"size": 10
} 查询匹配多个index
GET /index_2014*/_search
{} 因为Get请求携带请求体数据,不被广泛接受,所以上面的用Post请求可ok。

结构化查询

使用结构化查询,你需要传递query参数:

GET /_search
{
"query": YOUR_QUERY_HERE
}

空查询 - {} - 在功能上等同于使用match_all查询子句,正如其名字一样,匹配所有的文档:

GET /_search
{
"query": {
"match_all": {}
}
}

查询子句

一个查询子句一般使用这种结构:

{
QUERY_NAME: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}

或指向一个指定的字段:

{
QUERY_NAME: {
FIELD_NAME: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}
}

例如,你可以使用match查询子句用来找寻在tweet字段中找寻包含elasticsearch的成员:

{
"match": {
"tweet": "elasticsearch"
}
}

完整的查询请求会是这样:

GET /_search
{
"query": {
"match": {
"tweet": "elasticsearch"
}
}
}

查询与过滤

可以使用两种结构化语句: 结构化查询(Query DSL)和结构化过滤(Filter DSL)。 查询与过滤语句非常相似,但是它们由于使用目的不同而稍有差异。

一条过滤语句会询问每个文档的字段值是否包含着特定值:

  • created 的日期范围是否在 2013 到 2014 ?
  • status 字段中是否包含单词 "published" ?
  • lat_lon 字段中的地理位置与目标点相距是否不超过10km ?

一条查询语句与过滤语句相似,但问法不同:

查询语句会询问每个文档的字段值与特定值的匹配程度如何?

查询语句的典型用法是为了找到文档:

  • 查找与 full text search 这个词语最佳匹配的文档
  • 查找包含单词 run ,但是也包含runs, running, jog 或 sprint的文档
  • 同时包含着 quick, brown 和 fox --- 单词间离得越近,该文档的相关性越高
  • 标识着 lucene, search 或 java --- 标识词越多,该文档的相关性越高

一条查询语句会计算每个文档与查询语句的相关性,会给出一个相关性评分 _score,并且 按照相关性对匹配到的文档进行排序。 这种评分方式非常适用于一个没有完全配置结果的全文本搜索。

性能差异

使用过滤语句得到的结果集 -- 一个简单的文档列表,快速匹配运算并存入内存是十分方便的, 每个文档仅需要1个字节。这些缓存的过滤结果集与后续请求的结合使用是非常高效的。

查询语句不仅要查找相匹配的文档,还需要计算每个文档的相关性,所以一般来说查询语句要比过滤语句更耗时,并且查询结果也不可缓存。

幸亏有了倒排索引,一个只匹配少量文档的简单查询语句在百万级文档中的查询效率会与一条经过缓存的过滤语句旗鼓相当,甚至略占上风。 但是一般情况下,一条经过缓存的过滤查询要远胜一条查询语句的执行效率。

过滤语句的目的就是缩小匹配的文档结果集,所以需要仔细检查过滤条件。

什么情况下使用

原则上来说,使用查询语句做全文本搜索或其他需要进行相关性评分的时候,剩下的全部用过滤语句。

过滤查询

term过滤

term主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed的字符串(未经分析的文本数据类型):

    { "term": { "age":    26           }}
{ "term": { "date": "2014-09-01" }}
{ "term": { "public": true }}
{ "term": { "tag": "full_text" }}

terms 过滤

terms 跟 term 有点类似,但 terms 允许指定多个匹配条件。 如果某个字段指定了多个值,那么文档需要一起去做匹配:

{
"terms": {
"tag": [ "search", "full_text", "nosql" ]
}
}

range 过滤

range过滤允许我们按照指定范围查找一批数据:

{
"range": {
"age": {
"gte": 20,
"lt": 30
}
}
}

范围操作符包含:

  • gt :: 大于
  • gte:: 大于等于
  • lt :: 小于
  • lte:: 小于等于

exists 和 missing 过滤

exists 和 missing 过滤可以用于查找文档中是否包含指定字段或没有某个字段,类似于SQL语句中的IS_NULL条件

{
"exists": {
"field": "title"
}
}

这两个过滤只是针对已经查出一批数据来,但是想区分出某个字段是否存在的时候使用。

bool 过滤

bool 过滤可以用来合并多个过滤条件查询结果的布尔逻辑,它包含一下操作符:

  • must :: 多个查询条件的完全匹配,相当于 and。
  • must_not :: 多个查询条件的相反匹配,相当于 not。
  • should :: 至少有一个查询条件匹配, 相当于 or。

这些参数可以分别继承一个过滤条件或者一个过滤条件的数组:

{
"bool": {
"must": { "term": { "folder": "inbox" }},
"must_not": { "term": { "tag": "spam" }},
"should": [
{ "term": { "starred": true }},
{ "term": { "unread": true }}
]
}
}

match_all 查询

使用match_all 可以查询到所有文档,是没有查询条件下的默认语句。

{
"match_all": {}
}

此查询常用于合并过滤条件。 比如说你需要检索所有的邮箱,所有的文档相关性都是相同的,所以得到的_score为1

match 查询

match查询是一个标准查询,不管你需要全文本查询还是精确查询基本上都要用到它。

如果你使用 match 查询一个全文本字段,它会在真正查询之前用分析器先分析match一下查询字符:

{
"match": {
"tweet": "About Search"
}
}

如果用match下指定了一个确切值,在遇到数字,日期,布尔值或者not_analyzed 的字符串时,它将为你搜索你给定的值:

{ "match": { "age":    26           }}
{ "match": { "date": "2014-09-01" }}
{ "match": { "public": true }}
{ "match": { "tag": "full_text" }}

提示: 做精确匹配搜索时,你最好用过滤语句,因为过滤语句可以缓存数据。

match查询不可以用类似"+usid:2 +tweet:search"这样的语句。 它只能就指定某个确切字段某个确切的值进行搜索,而你要做的就是为它指定正确的字段名以避免语法错误。

multi_match 查询

multi_match查询允许你做match查询的基础上同时搜索多个字段:

{
"multi_match": {
"query": "full text search",
"fields": [ "title", "body" ]
}
}

bool 查询

bool 查询与 bool 过滤相似,用于合并多个查询子句。不同的是,bool 过滤可以直接给出是否匹配成功, 而bool 查询要计算每一个查询子句的 _score (相关性分值)。

  • must:: 查询指定文档一定要被包含。
  • must_not:: 查询指定文档一定不要被包含。
  • should:: 查询指定文档,有则可以为文档相关性加分。

以下查询将会找到 title 字段中包含 "how to make millions",并且 "tag" 字段没有被标为 spam。 如果有标识为 "starred" 或者发布日期为2014年之前,那么这些匹配的文档将比同类网站等级高:

{
"bool": {
"must": { "match": { "title": "how to make millions" }},
"must_not": { "match": { "tag": "spam" }},
"should": [
{ "match": { "tag": "starred" }},
{ "range": { "date": { "gte": "2014-01-01" }}}
]
}
}

提示: 如果bool查询下没有must子句,那至少应该有一个should子句。但是如果有must子句,那么没有should子句也可以进行查询。

查询与过滤条件的合并

查询语句和过滤语句可以放在各自的上下文中。 在 ElasticSearch API 中我们会看到许多带有 query 或 filter 的语句。 这些语句既可以包含单条 query 语句,也可以包含一条 filter 子句。 换句话说,这些语句需要首先创建一个query或filter的上下文关系。

复合查询语句可以加入其他查询子句,复合过滤语句也可以加入其他过滤子句。 通常情况下,一条查询语句需要过滤语句的辅助,全文本搜索除外。

所以说,查询语句可以包含过滤子句,反之亦然。 以便于我们切换 query 或 filter 的上下文。这就要求我们在读懂需求的同时构造正确有效的语句。

带过滤的查询语句

过滤一条查询语句

比如说我们有这样一条查询语句:

{
"match": {
"email": "business opportunity"
}
}

然后我们想要让这条语句加入 term 过滤,在收信箱中匹配邮件:

{
"term": {
"folder": "inbox"
}
}

search API中只能包含 query 语句,所以我们需要用 filtered 来同时包含 "query" 和 "filter" 子句:

{
"filtered": {
"query": { "match": { "email": "business opportunity" }},
"filter": { "term": { "folder": "inbox" }}
}
}

我们在外层再加入 query 的上下文关系:

GET /_search
{
"query": {
"filtered": {
"query": { "match": { "email": "business opportunity" }},
"filter": { "term": { "folder": "inbox" }}
}
}
}

单条过滤语句

在 query 上下文中,如果你只需要一条过滤语句,比如在匹配全部邮件的时候,你可以 省略 query 子句:

GET /_search
{
"query": {
"filtered": {
"filter": { "term": { "folder": "inbox" }}
}
}
}

如果一条查询语句没有指定查询范围,那么它默认使用 match_all 查询,所以上面语句 的完整形式如下:

GET /_search
{
"query": {
"filtered": {
"query": { "match_all": {}},
"filter": { "term": { "folder": "inbox" }}
}
}
}

查询语句中的过滤

有时候,你需要在 filter 的上下文中使用一个 query 子句。下面的语句就是一条带有查询功能 的过滤语句, 这条语句可以过滤掉看起来像垃圾邮件的文档:

GET /_search
{
"query": {
"filtered": {
"filter": {
"bool": {
"must": { "term": { "folder": "inbox" }},
"must_not": {
"query": { <1>
"match": { "email": "urgent business proposal" }
}
}
}
}
}
}
}

<1> 过滤语句中可以使用query查询的方式代替 bool 过滤子句。

提示: 我们很少用到的过滤语句中包含查询,保留这种用法只是为了语法的完整性。 只有在过滤中用到全文本匹配的时候才会使用这种结构。

验证查询

查询语句可以变得非常复杂,特别是与不同的分析器和字段映射相结合后,就会有些难度。

validate API 可以验证一条查询语句是否合法。

GET /gb/_validate/query
{
"query": {
"tweet" : {
"match" : "really powerful"
}
}
}

以上请求的返回值告诉我们这条语句是非法的:

{
"valid" : false
}

理解错误信息

想知道语句非法的具体错误信息,需要加上 explain 参数:

GET /gb/_validate/query?explain <1>
{
"query": {
"tweet" : {
"match" : "really powerful"
}
}
}

<1> explain 参数可以提供语句错误的更多详情。

很显然,我们把 query 语句的 match 与字段名位置弄反了:

{
"valid" : false,
"error" : "org.elasticsearch.common.ParsingException: no [query] registered for [tweet]"
}

理解查询语句

如果是合法语句的话,使用 explain 参数可以返回一个带有查询语句的可阅读描述, 可以帮助了解查询语句在ES中是如何执行的:

GET /gb/_validate/query?explain
{
"query": {
"match" : {
"tweet": "really powerful"
}
}
}

explanation 会为每一个索引返回一段描述,因为每个索引会有不同的映射关系和分析器:

{
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
},
"valid" : true,
"explanations" : [
{
"index" : "gb",
"valid" : true,
"explanation" : "tweet:really tweet:powerful"
}
]
}

从返回的 explanation 你会看到 match 是如何为查询字符串 "really powerful" 进行查询的, 首先,它被拆分成两个独立的词分别在 tweet 字段中进行查询。

而且,在索引us中这两个词为"really"和"powerful",在索引gb中被拆分成"really" 和 "power"。 这是因为我们在索引gb中使用了english分析器。

ES-结构化查询的更多相关文章

  1. ElasticSearch权威指南学习(结构化查询)

    请求体查询 简单查询语句(lite)是一种有效的命令行adhoc查询.但是,如果你想要善用搜索,你必须使用请求体查询(request body search)API. 空查询 我们以最简单的 sear ...

  2. elasticsearch结构化查询过滤语句-----4

    1.之前三节讲述的都是索引结构及内容填充的部分,既然添加了数据那我们的目的无非就是增产改查crudp,我先来讲讲查询-----结构化查询 我们看上图截图两种方式: 1)第一种,在索引index5类型s ...

  3. ElasticSearch 5学习(10)——结构化查询(包括新特性)

    之前我们所有的查询都属于命令行查询,但是不利于复杂的查询,而且一般在项目开发中不使用命令行查询方式,只有在调试测试时使用简单命令行查询,但是,如果想要善用搜索,我们必须使用请求体查询(request ...

  4. ElasticSearch(6)-结构化查询

    引用:ElasticSearch权威指南 一.请求体查询 请求体查询 简单查询语句(lite)是一种有效的命令行_adhoc_查询.但是,如果你想要善用搜索,你必须使用请求体查询(request bo ...

  5. SQL结构化查询语句

    SQL结构化查询语句 SQL定义了查询所有关系型数据库的规则. 1.通用语法 SQL语句可以单行或者多行书写,以分号结尾 可以使用空格和缩进增强可读性 不区分大小写,但是关键字建议大写 3种注释 注释 ...

  6. ElasticSearch 基本概念 and 索引操作 and 文档操作 and 批量操作 and 结构化查询 and 过滤查询

    基本概念 索引: 类似于MySQL的表.索引的结构为全文搜索作准备,不存储原始的数据. 索引可以做分布式.每一个索引有一个或者多个分片 shard.每一个分片可以有多个副本 replica. 文档: ...

  7. ORACLE结构化查询语句

  8. Elasticsearch 结构化搜索、keyword、Term查询

    前言 Elasticsearch 中的结构化搜索,即面向数值.日期.时间.布尔等类型数据的搜索,这些数据类型格式精确,通常使用基于词项的term精确匹配或者prefix前缀匹配.本文还将新版本的&qu ...

  9. ElasticSearch常用结构化搜索

    最近,需要用到ES的一些常用的结构化搜索命令,因此,看了一些官方的文档,学习了一下.结构化查询指的是查询那些具有内在结构的数据,比如日期.时间.数字都是结构化的. 它们都有精确的格式,我们可以对这些数 ...

随机推荐

  1. FSM有限状态机 ---C#、Unity

    抽象类State public interface State//定义状态接口 { void Init();//初始化 int GetCurrentStateId();//返回当前状态Id void ...

  2. CentOS 6 编译 TensorFlow for Java 以及 Maven Pom

    我们的系统环境 CentOS 6.5, JDK 1.8 更新yum源 $ yum update 安装 Python 2.7 $ yum install python27 python27-numpy ...

  3. Java修炼——四种方式解析XML_DOM4J

    四种方式解析XML:DOM     JDOM    DOM4J    SAX 注意: DOM4J使用是需要上传jar包的. 先写一个XML栗子: <?xml version="1.0& ...

  4. Python基础第一课

    Python基础 安装软件并配置环境变量 1.第一句python --初学后缀名可以是任何数 --后期学习需要导入模块时不是py后缀名会报错 2.两种执行方式 Python解释器 py文件路径 Pyt ...

  5. USB视频采集系统 视频测试软件将正式发布(方便调试测试各自摄像头,RAW,RGB,YUV)

    先上图,看看这个软件,学习fpga将近一年,了解视频图像开发方向也半年有余,不断学习不断总结,开发软件工具是为了更方便的学习新通信 主要相关知识: FPGA+SDRAM+VGA(双端口fifo技术) ...

  6. 【FastJson】使用学习

    FastJson使用学习 1.json转object.object转json List<CompanyLoopPicture> list = new ArrayList<Compan ...

  7. 深入理解JVM:元空间大小详细解析

    前言 JVM加载类的时候,需要记录类的元数据,这些数据会保存在一个单独的内存区域内,在Java 7里,这个空间被称为永久代(Permgen),在Java 8里,使用元空间(Metaspace)代替了永 ...

  8. Spring Integration - WS Outbound Gateway

    1.通过MessageSender客户化http连接参数 AbstractHttpWebServiceMessageSender有若干实现子类: - CommonsHttpMessageSender( ...

  9. Redis主从复制架构和Sentinel哨兵机制

    一.redis主从复制原理 redis主从同步策略:slave刚加入集群会触发一次全量同步(全量复制).全量同步之后,进行增量复制.slave优先是增量同步,如果增量同步失败会尝试从master节点进 ...

  10. hdu 1255 覆盖的面积 (扫描线求矩形交)

    覆盖的面积 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...