ElasticSearch常用操作:查询与聚合篇

[TOC]


0 说明

基于es 5.4和es 5.6,列举的是个人工作中经常用到的查询(只是工作中使用的是Java API),如果需要看完整的,可以参考官方相关文档
https://www.elastic.co/guide/en/elasticsearch/reference/5.4/search.html

1 查询

先使用一个快速入门来引入,然后后面列出的各种查询都是用得比较多的(在我的工作环境是这样),其它没怎么用的这里就不列出了。

1.1 快速入门

1.1.1 查询全部

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

GET index/type/_search

1.1.2 分页(以term为例)

GET index/type/_search
{
    "from":0,
    "size":100,
    "query":{
        "term":{
            "area":"GuangZhou"
        }
    }
}

1.1.3 包含指定字段(以term为例)

GET index/type/_search
{
    "_source":["hobby", "name"],
    "query":{
        "term":{
            "area":"GuangZhou"
        }
    }
}

1.1.4 排序(以term为例)

单个字段排序:

GET index/type/_search
{
    "query":{
        "term":{
            "area":"GuangZhou"
        }
    },
    "sort":[
        {"user_id":{"order":"asc"}},
        {"salary":{"order":"desc"}}
    ]
}

1.2 全文查询

查询字段会被索引和分析,在执行之前将每个字段的分词器(或搜索分词器)应用于查询字符串。

1.2.1 match query

{
  "query": {
    "match": {
      "content": {
        "query": "里皮恒大",
        "operator": "and"
      }
    }
  }
}

operator默认是or,也就是说,“里皮恒大”被分词为“里皮”和“恒大”,只要content中出现两个之一,都会搜索到;设置为and之后,只有同时出现都会被搜索到。

1.2.2 match_phrase query

文档同时满足下面两个条件才会被搜索到:

  • (1)分词后所有词项都要出现在该字段中
  • (2)字段中的词项顺序要一致
{
  "query": {
    "match_phrase": {
      "content": "里皮恒大"
    }
  }
}

1.3 词项查询

词项搜索时对倒排索引中存储的词项进行精确匹配,词项级别的查询通过用于结构化数据,如数字、日期和枚举类型。

1.3.1 term query

{
  "query": {
    "term": {
      "postdate": "2015-12-10 00:41:00"
    }
  }
}

1.3.2 terms query

term的升级版,如上面查询的postdate字段,可以设置多个。

{
  "query": {
    "terms": {
      "postdate": [
        "2015-12-10 00:41:00",
        "2016-02-01 01:39:00"
      ]
    }
  }
}

因为term是精确匹配,所以不要问,[]中的关系怎么设置and?这怎么可能,既然是精确匹配,一个字段也不可能有两个不同的值。

1.3.3 range query

匹配某一范围内的数据型、日期类型或者字符串型字段的文档,注意只能查询一个字段,不能作用在多个字段上。

数值:

{
  "query": {
    "range": {
      "reply": {
        "gte": 245,
        "lte": 250
      }
    }
  }
}

支持的操作符如下:

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

日期:

{
  "query": {
    "range": {
      "postdate": {
        "gte": "2016-09-01 00:00:00",
        "lte": "2016-09-30 23:59:59",
        "format": "yyyy-MM-dd HH:mm:ss"
      }
    }
  }
}

format不加也行,如果写的时间格式正确。

1.3.4 exists query

返回对应字段中至少有一个非空值的文档,也就是说,该字段有值(待会会说明这个概念)。

{
  "query": {
    "exists": {
      "field": "user"
    }
  }
}

参考《从Lucene到Elasticsearch:全文检索实战》中的说明。

以下文档会匹配上面的查询:

文档 说明
{"user":"jane"} 有user字段,且不为空
{"user":""} 有user字段,值为空字符串
{"user":"-"} 有user字段,值不为空
{"user":["jane"]} 有user字段,值不为空
{"user":["jane",null]} 有user字段,至少一个值不为空即可

下面的文档不会被匹配:

文档 说明
{"user":null} 虽然有user字段,但是值为空
{"user":[]} 虽然有user字段,但是值为空
{"user":[null]} 虽然有user字段,但是值为空
{"foo":"bar"} 没有user字段

1.3.5 ids query

查询具有指定id的文档。

{
  "query": {
    "ids": {
      "type": "news",
      "values": "2101"
    }
  }
}

类型是可选的,也可以以数据的方式指定多个id。

{
  "query": {
    "ids": {
      "values": [
        "2101",
        "2301"
      ]
    }
  }
}

1.4 复合查询

1.4.1 bool query

因为工作中接触到关于es是做聚合、统计、分类的项目,经常要做各种复杂的多条件查询,所以实际上,bool query用得非常多,因为查询条件个数不定,所以处理的逻辑思路时,外层用一个大的bool query来进行承载。(当然,项目中是使用其Java API)

bool query可以组合任意多个简单查询,各个简单查询之间的逻辑表示如下:

属性 说明
must 文档必须匹配must选项下的查询条件,相当于逻辑运算的AND
should 文档可以匹配should选项下的查询条件,也可以不匹配,相当于逻辑运算的OR
must_not 与must相反,匹配该选项下的查询条件的文档不会被返回
filter 和must一样,匹配filter选项下的查询条件的文档才会被返回,但是filter不评分,只起到过滤功能

一个例子如下:

{
  "query": {
    "bool": {
      "must": {
        "match": {
          "content": "里皮"
        }
      },
      "must_not": {
        "match": {
          "content": "中超"
        }
      }
    }
  }
}

需要注意的是,同一个bool下,只能有一个must、must_not、should和filter。

如果希望有多个must时,比如希望同时匹配"里皮"和"中超",但是又故意分开这两个关键词(因为事实上,一个must,然后使用match,并且operator为and就可以达到目的),怎么操作?注意must下使用数组,然后里面多个match对象就可以了:

{
  "size": 1,
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "content": "里皮"
          }
        },
        {
          "match": {
            "content": "恒大"
          }
        }
      ]
    }
  },
  "sort": [
    {
      "id": {
        "order": "desc"
      }
    }
  ]
}

当然must下的数组也可以是多个bool查询条件,以进行更加复杂的查询。

上面的查询等价于:

{
  "query": {
    "bool": {
      "must": {
        "match": {
          "content": {
            "query": "里皮恒大",
            "operator": "and"
          }
        }
      }
    }
  },
  "sort": [
    {
      "id": {
        "order": "desc"
      }
    }
  ]
}

1.5 嵌套查询

先添加下面一个索引:

PUT /my_index
{
  "mappings": {
    "my_type": {
      "properties": {
        "user":{
          "type": "nested",
          "properties": {
            "first":{"type":"keyword"},
            "last":{"type":"keyword"}
          }
        },
        "group":{
          "type": "keyword"
        }
      }
    }
  }
}

添加数据:

PUT my_index/my_type/1
{
  "group":"GuangZhou",
  "user":[
    {
      "first":"John",
      "last":"Smith"
    },
    {
      "first":"Alice",
      "last":"White"
    }
  ]
}

PUT my_index/my_type/2
{
  "group":"QingYuan",
  "user":[
    {
      "first":"Li",
      "last":"Wang"
    },
    {
      "first":"Yonghao",
      "last":"Ye"
    }
  ]
}

查询:

较简单的查询:

{
  "query": {
    "nested": {
      "path": "user",
      "query": {
        "term": {
          "user.first": "John"
        }
      }
    }
  }
}

较复杂的查询:

{
  "query": {
    "bool": {
      "must": [
        {"nested": {
          "path": "user",
          "query": {
            "term": {
              "user.first": {
                "value": "Li"
              }
            }
          }
        }},
        {
          "nested": {
            "path": "user",
            "query": {
              "term": {
                "user.last": {
                  "value": "Wang"
                }
              }
            }
          }
        }
      ]
    }
  }
}

1.6 补充:数组查询与测试

添加一个索引:

PUT my_index2
{
  "mappings": {
    "my_type2":{
      "properties": {
        "message":{
          "type": "text"
        },
        "keywords":{
          "type": "keyword"
        }
      }
    }
  }
}

添加数据:

PUT /my_index2/my_type/1
{
  "message":"keywords test1",
  "keywords":["美女","动漫","电影"]
}

PUT /my_index2/my_type/2
{
  "message":"keywords test2",
  "keywords":["电影","美妆","广告"]
}

搜索:

{
  "query": {
    "term": {
      "keywords": "广告"
    }
  }
}

Note1:注意设置字段类型时,keywords设置为keyword,所以使用term查询可以精确匹配,但设置为text,则不一定——如果有添加分词器,则可以搜索到;如果没有,而是使用默认的分词器,只是将其分为一个一个的字,就不会被搜索到。这点尤其需要注意到。

Note2:对于数组字段,也是可以做桶聚合的,做桶聚合的时候,其每一个值都会作为一个值去进行分组,而不是整个数组进行分组,可以使用上面的进行测试,不过需要注意的是,其字段类型不能为text,否则聚合会失败。

Note3:所以根据上面的提示,一般纯数组比较适合存放标签类的数据,就像上面的案例一样,同时字段类型设置为keyword,而不是text,搜索时进行精确匹配就好了。

2 聚合

2.1 指标聚合

相当于MySQL的聚合函数。

max

{
  "size": 0,
  "aggs": {
    "max_id": {
      "max": {
        "field": "id"
      }
    }
  }
}

size不设置为0,除了返回聚合结果外,还会返回其它所有的数据。

min

{
  "size": 0,
  "aggs": {
    "min_id": {
      "min": {
        "field": "id"
      }
    }
  }
}

avg

{
  "size": 0,
  "aggs": {
    "avg_id": {
      "avg": {
        "field": "id"
      }
    }
  }
}

sum

{
  "size": 0,
  "aggs": {
    "sum_id": {
      "sum": {
        "field": "id"
      }
    }
  }
}

stats

{
  "size": 0,
  "aggs": {
    "stats_id": {
      "stats": {
        "field": "id"
      }
    }
  }
}

2.2 桶聚合

相当于MySQL的group by操作,所以不要尝试对es中text的字段进行桶聚合,否则会失败。

Terms

相当于分组查询,根据字段做聚合。

{
  "size": 0,
  "aggs": {
    "per_count": {
      "terms": {
        "size":100,
        "field": "vtype",
        "min_doc_count":1
      }
    }
  }
}

在桶聚合的过程中还可以进行指标聚合,相当于mysql做group by之后,再做各种max、min、avg、sum、stats之类的:

{
  "size": 0,
  "aggs": {
    "per_count": {
      "terms": {
        "field": "vtype"
      },
      "aggs": {
        "stats_follower": {
          "stats": {
            "field": "realFollowerCount"
          }
        }
      }
    }
  }
}

Filter

相当于是MySQL根据where条件过滤出结果,然后再做各种max、min、avg、sum、stats操作。

{
  "size": 0,
  "aggs": {
    "gender_1_follower": {
      "filter": {
        "term": {
          "gender": 1
        }
      },
      "aggs": {
        "stats_follower": {
          "stats": {
            "field": "realFollowerCount"
          }
        }
      }
    }
  }
}

上面的聚合操作相当于是:查询gender为1的各个指标。

Filters

在Filter的基础上,可以查询多个字段各自独立的各个指标,即对每个查询结果分别做指标聚合。

{
  "size": 0,
  "aggs": {
    "gender_1_2_follower": {
      "filters": {
        "filters": [
          {
            "term": {
              "gender": 1
            }
          },
          {
            "term": {
              "gender": 2
            }
          }
        ]
      },
      "aggs": {
        "stats_follower": {
          "stats": {
            "field": "realFollowerCount"
          }
        }
      }
    }
  }
}

Range

{
  "size": 0,
  "aggs": {
    "follower_ranges": {
      "range": {
        "field": "realFollowerCount",
        "ranges": [
          {
            "to": 500
          },
          {
            "from": 500,
            "to": 1000
          },
          {
            "from": 1000,
            "to": 1500
          },
          {
            "from": "1500",
            "to": 2000
          },
          {
            "from": 2000
          }
        ]
      }
    }
  }
}

to:小于,from:大于等于

Date Range

跟上面一个类似的,其实只是字段为日期类型的,然后范围值也是日期。

原文地址:http://blog.51cto.com/xpleaf/2307572

时间: 2024-10-29 14:43:57

ElasticSearch常用操作:查询与聚合篇的相关文章

ElasticSearch常用操作:文档篇

[TOC] 1 新建文档 1.1 指定id PUT my_blog/article/1 { "id":1, "title":"elasticsearch", "posttime":"2017-05-01", "content":"elasticsearch is helpfull!" } 返回: { "_index": "my_blog&

Elasticsearch 常用基本查询

安装启动很简单,参考官网步骤:https://www.elastic.co/downloads/elasticsearch 为了介绍Elasticsearch中的不同查询类型,我们将对带有下列字段的文档进行搜索:title(标题),authors(作者),summary(摘要),release date(发布时间)以及number of reviews(评论数量),首先,让我们创建一个新的索引,并通过bulk API查询文档: 为了展示Elasticsearch中不同查询的用法,首先在Elast

Elasticsearch常用操作:映射篇

[TOC] 其实就是es的字段类型是由es来做自动检测还是由我们自己来指定,因此会分为动态映射和静态映射. 1 动态映射 1.1 映射规则 JSON格式的数据 自动推测的字段类型 null 没有字段被添加 true or false boolean类型 浮点类型数字 float类型 数字 long类型 JSON对象 object类型 数组 由数组中第一个非空值决定 string 有可能是date类型(开启日期检测).double或long类型.text类型.keyword类型 1.2 日期检测

ElasticSearch 常用的查询过滤语句

query 和  filter 的区别请看: http://www.cnblogs.com/ghj1976/p/5292740.html    Filter DSL   term 过滤 term主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed 的字符串(未经分析的文本数据类型): { "term": { "age":    26           }} { "term": { "date":   &

elasticsearch常用操作

3.3.1 Preparing a query 准备查询请求 import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.Client; import org.elasticsearch.search.SearchHit; SearchResponse response = client.prepareSearch("library") .addFields("t

Elasticsearch常用操作API

1. 查询所有的索引 [[email protected] cx]# curl '10.0.0.5:9200/_cat/indices?v' health status index    pri rep docs.count docs.deleted store.size pri.store.size  yellow open   customer   5   1          2            0      6.6kb          6.6kb  yellow open   b

redis常用操作和操作键值

string.list常用操作 string数据创建.覆盖及设置过期时间 127.0.0.1:6379> get key1 ? ? ? ? 查看原来的key1的值 "b" 127.0.0.1:6379> set key1 123 ? ? 覆盖创建一个新的key1的string的值 OK 127.0.0.1:6379> get key1 ? ? ? ? 查看 "123" 127.0.0.1:6379> setnx key1 456 ? ? 使用

[Elasticsearch] 过滤查询以及聚合(Filtering Queries and Aggregations)

本章翻译自Elasticsearch官方指南的Filtering Queries and Aggregations一章. 过滤查询以及聚合 A natural extension to aggregation scoping is filtering. Because the aggregation operates in the context of the query scope, any filter applied to the query will also apply to the

vim常用操作和使用技巧

vi是linux与unix下的常用文本编辑器,其运行稳定,使用方便,本文将分两部分对其常用操作技巧和配置进行阐述,其中参考了网上的一些文章,对作者表示感谢 PART1 操作技巧 说明: 以下的例子中 xxx 表示在命令模式下输入 xxx 并回车 以下的例子中 :xxx 表示在扩展模式下输入 xxx 并回车 ()中的命令表示相关命令.[]表示命令等同 在编辑模式或可视模式下输入的命令会另外注明. 移动光标 在 vi 中, 移动光标和编辑是两件事, 正因为区分开来, 所以可以很方便的进行光标定 位和