ElasticSearch - 查询语法

本文详细介绍了Elasticsearch的查询语法,包括search的timeout、Query_string的使用限制、Query DSL中的全文检索、短语搜索、bool查询、复合查询、高亮搜索以及分页、过滤、聚合查询等内容。强调了term和match的区别,并展示了如何设置mapping以优化搜索性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


search的timeout

  1. 设置:默认没有timeout,如果设置了timeout,那么会执行timeout机制。
  2. Timeout机制:假设用户查询结果有1W条数据,但是需要10s才能查询完毕,但是用户设置了1s的timeout,那么不管当前一共查询到了多少数据,都会在1″后ES讲停止查询,并返回当前数据。
  3. 用法:GET /_search?timeout=1s/ms/m

在返回值中, 如果是 "timed_out" : false, 说明没有超时, 返回的是全量数据

 


Query_string 一般不用于生产环境

  • 查询所有:GET /product/_search
  • 带参数:GET /product/_search?q=name:xiaomi
  • 分页:GET /product/_search?from=0&size=2&sort=price:asc

 


Query DSL

match_all:匹配所有

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

 

 

match会分词, 各个词之间是or的关系 -> name中包含“nfc” 或者 包含"phone"

GET /product/_search
{
  "query": {
    "match": {
      "name": "nfc phone"
    }
  }
}

 

 

sort:按照价格倒序排序   一旦有了sort, es为了提升性能, 就不会去算score, 因为没有必要

GET /product/_search
{
  "query": {
    "multi_match": {
      "query": "nfc",
      "fields": ["name","desc"]
    }
  },
  "sort": [
    {
      "price": "desc"
    }
  ]
}

multi_match:根据多个字段查询一个关键词,name和desc中包含“nfc”的doc

 

GET /product/_search
{
  "query": {
    "multi_match": {
      "query": "nfc",
      "fields": ["name","desc"]
    }
  },
  "sort": [
    {
      "price": "desc"
    }
  ]
}

_source 元数据:想要让返回的字段少一些, 可以用这个

 

GET /product/_search
{
  "query":{
    "match": {
      "name": "nfc"
    }
  },
  "_source": ["name","price"]
}

分页:查询第一页(每页两条数据), 但是要注意deep-paging问题

 

GET /product/_search
{
  "query":{
    "match_all": {}
  },
  "sort": [
    {
      "price": "asc"
    }
  ],
  "from": 0,
  "size": 2
}

 

Full-text queries:全文检索

term:不会被分词

GET /product/_search
{
  "query": {
    "term": {
      "name": "nfc"
    }
  }
}

    "hits" : [ {
        "_score" : 0.90928507,
        "_source" : {
          "name" : "nfc phone"
        }
      }, {
        "_score" : 0.76209855,
        "_source" : {
          "name" : "xiaomi nfc phone"
        }
      }
    ]

 

 

 

match和term区别

# 这里因为没有分词,所以从倒排索引中查询 "nfc phone" 没有结果

GET /product/_search
{
  "query": {
    "term": {
      "name": "nfc phone"
    }
  }
}
# name中既要有nfc, 又必须有phone

GET /product/_search
{
  "query": {
    "bool": {
      "must": [
        {"term":{"name":"nfc"}},
        {"term":{"name":"phone"}}
      ]
    }
  }
}

     {
        "_score" : 1.4691012,
        "_source" : {
          "name" : "nfc phone"
        }
      }, {
        "_score" : 1.2312969,
        "_source" : {
          "name" : "xiaomi nfc phone"
        }
      }

 

# name中要有nfc 或者 要有phone

GET /product/_search
{
  "query": {
    "terms": {
      "name":["nfc","phone"]
    }
  }
}

    {
        "_score" : 1.0,
        "_source" : {
          "name" : "xiaomi phone"
        }
      }, {
        "_score" : 1.0,
        "_source" : {
          "name" : "xiaomi nfc phone"
        }
      }, {
        "_score" : 1.0,
        "_source" : {
          "name" : "nfc phone"
        }
      }

# match会分词, 词与词之间的关系是or

GET /product/_search
{
  "query": {
    "match": {
      "name": "nfc phone"
    }
  }
}

    {
        "_score" : 1.4691012,
        "_source" : {
          "name" : "nfc phone"
        }
      }, {
        "_score" : 1.2312969,
        "_source" : {
          "name" : "xiaomi nfc phone"
        }
      }, {
        "_score" : 0.5598161,
        "_source" : {
          "name" : "xiaomi phone"
        }
      }

 

☆全文检索

GET /product/_search
{
  "query": {
    "match": {
      "name": "xiaomi nfc zhineng phone"
    }
  }
}

#验证分词

GET /_analyze
{
  "analyzer": "standard"
  ,"text": "xiaomi nfc zhineng phone"
}

返回

"tokens" : [
    {
      "token" : "xiaomi",
      "start_offset" : 0,
      "end_offset" : 6,
      "type" : "<ALPHANUM>",
      "position" : 0
    }, {
      "token" : "nfc",
      "start_offset" : 7,
      "end_offset" : 10,
      "type" : "<ALPHANUM>",
      "position" : 1
    }, {
      "token" : "zhineng",
      "start_offset" : 11,
      "end_offset" : 18,
      "type" : "<ALPHANUM>",
      "position" : 2
    }, {
      "token" : "phone",
      "start_offset" : 19,
      "end_offset" : 24,
      "type" : "<ALPHANUM>",
      "position" : 3
    }
  ]

 

phrase search:短语搜索,和全文检索相反,“nfc phone”会作为一个短语去检索

# nfc和phone必须同时包含

GET /product/_search
{
  "query": {
    "match_phrase": {
      "name": "nfc phone"
    }
  }
}

 


Query and filter:查询和过滤

bool:可以组合多个查询条件,bool查询也是采用more_matches_is_better的机制,因此满足must和should子句的文档将会合并起来计算分值

bool下的多个查询条件, 是AND的关系

 
 scorecache 

must

必须满足

计算 子句(查询)必须出现在匹配的文档中, AND: 子句全都要满足

filter

过滤器

不计算缓存

子句(查询)必须出现在匹配的文档中。但是不像 must查询的分数将被忽略。Filter子句在filter上下文中执行,这意味着计分被忽略,并且子句被考虑用于缓存

should

计算 

子句(查询)应出现在匹配的文档中

minimum_should_match: 1   OR: 子句至少满足一个 

must_not

必须不满足

不计算缓存

子句(查询)不得出现在匹配的文档中。子句在过滤器上下文中执行,这意味着计分被忽略,并且子句被视为用于缓存。由于忽略计分,0因此将返回所有文档的分数。

 

 

 

 

 

 

 

 

# 首先筛选name包含“xiaomi phone”, 并且价格大于1999的数据(不排序)

GET /product/_search
{
  "query": {
    "bool":{
      "must": [
        { "match": { "name": "xiaomi"}},
        { "match": { "desc": "shouji"}}
      ],
      "filter": [
        { "match_phrase": { "name":"xiaomi phone"}},
        { "range": {
          "price": {
            "gt": 1999
          }
        }}
      ]
    }
  }
}
# bool多条件 name包含xiaomi 不包含erji 描述里包不包含nfc都可以,价钱要大于等于4999

GET /product/_search
{
  "query": {
    "bool": {

      "must": [              # name中必须包含“xiaomi”
        {"match": { "name": "xiaomi"}}
      ],

      "must_not": [          # name中必须不能包含“erji”
        {"match": { "name": "erji"}}
      ],

      "should": [    #should中至少满足0个条件,参见下面的minimum_should_match的解释
        {"match": {
          "desc": "nfc" 
        }}
      ],

      "filter": [      
        {"range": {
          "price": {         # 筛选价格大于4999的doc
            "gt": 4999
          }
        }}
      ]

    }
  }
}

嵌套查询:

minimum_should_match:参数指定should返回的文档必须匹配的子句的数量或百分比。如果bool查询包含至少一个should子句,而没有must或 filter子句,则默认值为1。否则,默认值为0

GET /product/_search
{
  "query": {
    "bool":{
      
      "should": [
        {"range": {
          "price": {"gt":1999}
        }},
         {"range": {
          "price": {"gt":3999}
        }}
      ],
      "minimum_should_match": 1
    }
  }
}

 

Compound queries:组合查询

想要一台带NFC功能的 或者 小米的手机 但是不要耳机

SELECT * from product

where (`name` like "%xiaomi%" or `name` like '%nfc%')

AND `name` not LIKE '%erji%'

GET /product/_search
{
  "query": {
    "constant_score":{
      "filter": {
        "bool": {
          "should":[
            {"term":{"name":"xiaomi"}},
            {"term":{"name":"nfc"}}
          ],
          "must_not":[
            {"term":{"name":"erji"}}
          ]
        }
      },
      "boost": 1.2
    }
  }
}

 

搜索一台"xiaomi nfc phone" 或者 "满足 是phone 并且 price <= 2999"

GET /product/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "bool":{
          "should":[
            {"match_phrase":{"name":"xiaomi nfc phone"}},
            {
              "bool":{
                "must":[
                  {"term":{"name":"phone"}},
                  {"range":{"price":{"lte":"2999"}}}
                ]
              }
            }
          ]
        }
      }
    }
  }
}

 

高亮搜索 Highlight search

GET /product/_search
{
  "query" : {
    "match_phrase" : {
      "name" : "nfc phone"
    }
  },
  "highlight":{
    "fields":{
       "name":{}
    }
  }
}

返回

        "highlight" : {
          "name" : [
            "xiaomi <em>nfc</em> <em>phone</em>"
          ]
        }


Deep paging图解

  1. 解释:当你的数据超过1W,不要使用
  2. 返回结果不要超过1000个,500以下为宜
  3. 解决办法:
    • 尽量避免深度分页查询
    • 使用Scroll search(只能下一页,没办法上一页,不适合实时查询)

Scroll search:图解

解决 deep paging问题

GET /product/_search?scroll=1m
{
  "query": {
    "match_all": {}
  }
  ,"size": 2
}

返回

{
  "_scroll_id" : "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFGtzWmRxM1VCY1BvN0psOXRPSXNZAAAAAAAARj0WZlhVLUJScjdTS2FkdGN4ZzY4MlA0QQ==",
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 5,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "product",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "name" : "xiaomi phone",
          "desc" : "shouji zhong de zhandouji",
          "price" : 3999,
          "tags" : [
            "xingjiabi",
            "fashao",
            "buka"
          ]
        }
      },
      {
        "_index" : "product",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "name" : "xiaomi nfc phone",
          "desc" : "zhichi quangongneng nfc,shouji zhong de jianjiji",
          "price" : 4999,
          "tags" : [
            "xingjiabi",
            "fashao",
            "gongjiaoka"
          ]
        }
      }
    ]
  }
}

得到scroll_id之后, 再次请求可以拿下一页的数据, scroll不能拿上一页的数据

GET /_search/scroll
{
  "scroll":"1m"  # 每次查询再次续命1分钟, 不加这个参数, 只能请求一次, 没等过期就清理了
  ,"scroll_id" : "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFGhjWmNxM1VCY1BvN0psOXRsSXUxAAAAAAAARjAWZlhVLUJScjdTS2FkdGN4ZzY4MlA0QQ=="
}

返回

{
  "took" : 1,
  "timed_out" : false,
  "terminated_early" : true,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 5,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "product",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 1.0,
        "_source" : {
          "name" : "nfc phone",
          "desc" : "shouji zhong de hongzhaji",
          "price" : 2999,
          "tags" : [
            "xingjiabi",
            "fashao",
            "menjinka"
          ]
        }
      },
      {
        "_index" : "product",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 1.0,
        "_source" : {
          "name" : "xiaomi erji",
          "desc" : "erji zhong de huangmenji",
          "price" : 999,
          "tags" : [
            "low",
            "bufangshui",
            "yinzhicha"
          ]
        }
      }
    ]
  }
}


filter缓存原理:图解

 

 

 


 

Mapping

mapping就是ES数据字段field的type元数据,ES在创建索引的时候,dynamic mapping会自动为不同的数据指定相应mapping,mapping中包含了字段的类型、搜索方式(exact value或者full text)、分词器等。

# 查看mapping

GET /product/_mappings

Dynamic mapping

 

  • “Elasticsearch”:text/keyword           
  • 123456                 =>   long               ?为什么不是integer
  • 123.123                 =>   double    
  • true false               =>   boolean
  • 2020-05-20           =>   date

为啥price是long类型而不是integer?

因为es的mapping_type是由JSON分析器检测数据类型,而Json没有隐式类型转换(integer=>long or float=> double),所以dynamic mapping会选择一个比较宽的数据类型。


搜索方式

  • exact value 精确匹配:在倒排索引过程中,分词器会将field作为一个整体创建到索引中
  • full text全文检索:分词、近义词同义词、混淆词、大小写、词性、过滤、时态转换等(normaliztion)

ES数据类型:

核心类型

  1. 数字类型
    1. longintegershortbytedoublefloathalf_floatscaled_float
    2. 在满足需求的情况下,尽可能选择范围小的数据类型。
  2. 字符串:string
    1. keyword不会被分词, 建倒排索引的时候, 用的是整体值. 适用于索引结构化的字段,可以用于过滤、排序、聚合。keyword类型的字段只能通过精确值(exact value)搜索到。Id应该用keyword
    2. text当一个字段是要被全文搜索的,比如Email内容、产品描述,这些字段应该使用text类型。设置text类型以后,字段内容会被分析,在生成倒排索引以前,字符串会被分析器分成一个一个词项text类型的字段不用于排序,很少用于聚合。(解释一下为啥不会为text创建索引字段数据会占用大量堆空间,尤其是在加载高基数text字段时。字段数据一旦加载到堆中,就在该段的生命周期内保持在那里。同样,加载字段数据是一个昂贵的过程,可能导致用户遇到延迟问题。这就是默认情况下禁用字段数据的原因
    3. 有时,在同一字段中同时具有全文本(text)和关键字(keyword)版本会很有用:一个用于全文本搜索,另一个用于聚合和排序。
  3. date(时间类型):exact value
  4. 布尔类型:boolean
  5. binary(二进制):binary
  6. range区间类型:integer_range、float_range、long_range、double_range、date_range
    1. 复杂类型:
      1. Object:用于单个JSON对象
      2. Nested:用于JSON对象数组
    2. 地理位置:
      1. Geo-point:纬度/经度积分
      2. Geo-shape:用于多边形等复杂形状
    3. 特有类型:
      1. IP地址:ip 用于IPv4和IPv6地址
      2. Completion:提供自动完成建议
      3. Tocken_count:计算字符串中令牌的数量
      4. Murmur3在索引时计算值的哈希并将其存储在索引中
      5. Annotated-text:索引包含特殊标记的文本(通常用于标识命名实体)
      6. Percolator:接受来自query-dsl的查询
      7. Join:为同一索引内的文档定义父/子关系
      8. Rank features:记录数字功能以提高查询时的点击率。
      9. Dense vector:记录浮点值的密集向量。
      10. Sparse vector:记录浮点值的稀疏向量。
      11. Search-as-you-type:针对查询优化的文本字段,以实现按需输入的完成
      12. Alias:为现有字段定义别名。
      13. Flattened:允许将整个JSON对象索引为单个字段。
      14. Shapeshape 对于任意笛卡尔几何。
      15. Histogramhistogram 用于百分位数聚合的预聚合数值。
      16. Constant keywordkeyword当所有文档都具有相同值时的情况的 专业化。
    4. Array(数组):在Elasticsearch中,数组不需要专用的字段数据类型。默认情况下,任何字段都可以包含零个或多个值,但是,数组中的所有值都必须具有相同的数据类型。
    5. ES 7新增:
      1. Date_nanos:date plus 纳秒
      2. Features:
      3. Vector:as
    6. 手工创建mapping
PUT /product
{
  "mappings": {
    "properties": {
        "field": {
          "mapping_parameter": "parameter_value"
        }
    }
  }
}

Mapping parameters

  • index:是否对当前字段创建索引,默认true,如果不创建索引, 该字段不会通过索引被搜索到, 但是仍然会在source元数据中展示
  • analyzer:指定分析器(character filtertokenizerToken filters)。
  • boost:对当前字段相关度的评分权重,默认1, es5废弃
  • coerce:是否允许强制类型转换  对于类型为int, 值为1的doc,   true的话, “1”和1都能搜到,   false的话 “1”不会转换成1, 也就搜不到
  • copy_to:可以把单个/多个字段, copy到一个字段里, 然后搜索的时候, 只搜这一个字段就行
# 定义好表结构, field1, field2的内容会映射到field_all

PUT copy_to
{
  "mappings": {
    "properties": {
      "field1": {
        "type": "text"
        ,"copy_to": "field_all"
      }
      ,"field2": {
        "type": "text"
        ,"copy_to": "field_all"
      }
      ,"field_all": {
        "type": "text"
      }
    }
  }
}

 

 

往copy_to索引里插入一行, field1和field2带值, field_all不用给值

PUT copy_to/_doc/1
{
  "field1":"xiaomi"
  ,"field2":"nfc"
  ,"field_all":""
}

然后对field_all字段进行搜索

GET copy_to/_search
{
  "query": {
    "match": {
      "field_all": "nfc"
    }
  }
}

返回

"hits" : [
      {
        "_index" : "copy_to",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.2876821,
        "_source" : {
          "field1" : "xiaomi",
          "field2" : "nfc",
          "field_all" : ""
        }
      }
    ]

由此可见, field_all在doc里是没有值的, 但是field_all字段对应的倒排索引里是存了field1和field2的分词的


doc_values

正排索引, 类似于mysql索引

为了提升排序和聚合效率,默认true,如果确定不需要对字段进行排序或聚合,也不需要通过脚本访问字段值,则可以禁用doc值以节省磁盘空间

不支持textannotated_text, 太过于消耗磁盘和内存

如果一定要根据text字段做聚合操作, 那么就把这个字段设置为 "fielddata":true

dynamic

控制是否可以动态添加新字段    线上索引一般设为strict, 禁止太灵活的用法

  1. true 新检测到的字段将添加到映射中。(默认)
  2. false 新检测到的字段将被忽略。这些字段将不会被索引,因此将无法搜索,但仍会出现在_source返回的匹配项中。这些字段不会添加到映射中,必须显式添加新字段。
  3. strict 如果检测到新字段,则会引发异常并拒绝文档。必须将新字段显式添加到映射中

eager_global_ordinals

用于聚合的字段上, 优化聚合性能 , 用于热数据

eager_global_ordinals不适用于Frozen indices

什么是 " Frozen indices " :

  1. Frozen indices(冻结索引):有些索引使用率很高,会被保存在内存中,有些使用率特别低,宁愿在使用的时候重新创建,在使用完毕后丢弃数据
  2. Frozen indices的数据命中频率小,是绝对的冷数据,不会被保存在内存中,堆空间占用比普通索引少得多
  3. Frozen indices是只读的,请求可能是秒级或者分钟级。

enable 是否创建倒排索引

可以对字段操作,也可以对索引操作,如果不创建索引,仍然可以检索并在_source元数据中展示,谨慎使用,该状态无法修改。

enable:false 和 index: false的意思差不多

# enable用于整个索引

PUT my_index {
  "mappings": {
    "enabled": false
  }
}
# enable用于单个字段

PUT my_index{
  "mappings": {
    "properties": {
      "session_data": {
        "type": "object",
        "enabled": false
      }
    }
  }
}

 

fielddata

查询时内存数据结构,在首次用当前字段聚合、排序或者在脚本中使用时,需要字段为fielddata数据结构,并且创建倒排索引保存到堆中

一般来说, 聚合是不支持textannotated_text, 太过于消耗磁盘和内存

但如果一定要根据text字段做聚合操作, 那么就把这个字段设置为 "fielddata":true

但是这种方式性能很低, 建议再创建一个keyword嵌套的子字段

 

fields

给field创建多字段,用于不同目的(全文检索text或者聚合分析排序keyword )

 

format:格式化

"date": {
  "type":   "date",
  "format": "yyyy-MM-dd"
 }

ignore_above

修饰keyword类型的字段, 超过长度将被忽略

ignore_malformed

忽略类型错误

PUT my_index{
  "mappings": {
    "properties": {
      "number_one": {
        "type": "integer",
        "ignore_malformed": true
      },
      "number_two": {
        "type": "integer"
      }
    }
  }
}
// 虽然有异常 但是不抛出
PUT my_index/_doc/1
{
  "text":       "Some text value",
  "number_one": "foo" 
}   

// 数据格式不对
PUT my_index/_doc/2
{
  "text":       "Some text value",
  "number_two": "foo"
}

 

 

index_options:控制将哪些信息添加到反向索引中以进行搜索和突出显示。仅用于text字段

Index_phrases:提升exact_value查询速度,但是要消耗更多磁盘空间

Index_prefixes:前缀搜索

  1. min_chars:前缀最小长度,>0,默认2(包含)
  2. max_chars:前缀最大长度,<20,默认5(包含)
"index_prefixes": {
  "min_chars" : 1,
  "max_chars" : 10
}

 

 

meta:附加元数据

normalizer:

norms:是否禁用评分(在filter和聚合字段上应该禁用)。

null_value:为null值设置默认值

如果doc的field1字段是null, 就把"0"赋值给该doc的field1字段

PUT my_index
{
  "mappings": {
    "properties": {
      "field1": {
        "type": "text"
        "null_value": "0"
      }
    }
  }
}

 

 

position_increment_gap:?

proterties:除了mapping还可用于object的属性设置

search_analyzer:设置单独的查询时分析器:

PUT my_index{
  "settings": {
    "analysis": {
      "filter": {
        "autocomplete_filter": {
          "type": "edge_ngram",
          "min_gram": 1,
          "max_gram": 20
        }
      },
      "analyzer": {
        "autocomplete": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "autocomplete_filter"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "text": {
        "type": "text",
        "analyzer": "autocomplete",    // 建索引的时候, 用的分词器
        "search_analyzer": "standard"  // search的时候用的分词器
      }
    }
  }
}
PUT my_index/_doc/1
{
  "text": "Quick Brown Fox"
}


GET my_index/_search
{
  "query": {
    "match": {
      "text": {
        "query": "Quick Br",
        "operator": "and"
      }
    }
  }
}

 

 

 

similarity:为字段设置相关度算法,支持BM25claassicTF-IDF)、boolean

store:设置字段是否仅查询

term_vector:

 


聚合查询

demo1: group by

以tag维度每个产品的数量,即每个标签, 在的基础上增加筛选条件:统计价格大于1999的数据

 

 

 

GET /product/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "range": {
            "price": {
              "gt": 1999
            }
          }
        }
      ]
    }
  }, 
  "aggs": {
    "aggName": {
      "terms": {
        "field": "tags.keyword"
      }
    }
  },
  "size": 0
}

返回

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "aggName" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [ {
          "key" : "fashao",
          "doc_count" : 3
        }, {
          "key" : "xingjiabi",
          "doc_count" : 3
        }, {
          "key" : "buka",
          "doc_count" : 1
        }, {
          "key" : "gongjiaoka",
          "doc_count" : 1
        }, {
          "key" : "menjinka",
          "doc_count" : 1
        }
      ]
    }
  }
}

demo2: avg

基于tags中的每个值, 求出平均价格

GET /product/_search
{
  "aggs": {
    "myAVG": {
      "terms": {
        "field": "tags.keyword",  // 相当于mysql中的GROUP BY tags.keyword
        "order": {
          "avg_price": "desc"
        }
      },
      "aggs": {
        "avg_price": {
          "avg": {
            "field": "price" // 相当于mysql中的SELECT AVG(price) FROM product
          }
        }
      }
    }
  },
  "size": 0
}

返回

 

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 5,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "myAVG" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 1,
      "buckets" : [
        {
          "key" : "gongjiaoka",
          "doc_count" : 1,
          "avg_price" : {
            "value" : 4999.0
          }
        },
        {
          "key" : "buka",
          "doc_count" : 1,
          "avg_price" : {
            "value" : 3999.0
          }
        },
        {
          "key" : "fashao",
          "doc_count" : 3,
          "avg_price" : {
            "value" : 3999.0    //    ( 2999 + 3999 + 4999 ) / 3 = 3999
          }
        },
        {
          "key" : "xingjiabi",
          "doc_count" : 3,
          "avg_price" : {
            "value" : 3999.0
          }
        },
        {
          "key" : "menjinka",
          "doc_count" : 1,
          "avg_price" : {
            "value" : 2999.0
          }
        },
        {
          "key" : "bufangshui",
          "doc_count" : 1,
          "avg_price" : {
            "value" : 999.0
          }
        },
        {
          "key" : "low",
          "doc_count" : 1,
          "avg_price" : {
            "value" : 999.0
          }
        },
        {
          "key" : "yinzhicha",
          "doc_count" : 1,
          "avg_price" : {
            "value" : 999.0
          }
        },
        {
          "key" : "lowbee",
          "doc_count" : 1,
          "avg_price" : {
            "value" : 399.0
          }
        },
        {
          "key" : "xuhangduan",
          "doc_count" : 1,
          "avg_price" : {
            "value" : 399.0
          }
        }
      ]
    }
  }
}
 

 

 

分组聚合

按照千元机:1000以下  中端机:2000-3000 高端机:3000以上分组聚合,分别计算数量

GET /product/_search
{
  "aggs": {
    "aggTags": {
      "range": {
        "field": "price",
        "ranges": [
          {
            "from": 100,
            "to": 1000
          },{
            "from": 1000,
            "to": 2000
          },{
            "from": 3000
          }
        ]
      },
      "aggs": {
        "priceAgg": {
          "avg": {
            "field": "price"  // SELECT AVG(price)
          }
        }
      }
    }
  },
  "size": 0
}

返回

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 5,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "aggTags" : {
      "buckets" : [
        {
          "key" : "100.0-1000.0",
          "from" : 100.0,
          "to" : 1000.0,
          "doc_count" : 2,
          "priceAgg" : {
            "value" : 699.0
          }
        },
        {
          "key" : "1000.0-2000.0",
          "from" : 1000.0,
          "to" : 2000.0,
          "doc_count" : 0,
          "priceAgg" : {
            "value" : null
          }
        },
        {
          "key" : "3000.0-*",
          "from" : 3000.0,
          "doc_count" : 2,
          "priceAgg" : {
            "value" : 4499.0
          }
        }
      ]
    }
  }
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值