搜索引擎ElasticSearch之(7)、聚合查詢

1、度量聚合

度量聚合從文檔中提取值并進(jìn)行計算,這些值通常從文檔中的字段中提取出來,也可以使用腳本進(jìn)行計算。數(shù)字型度量聚合是一種特殊類型的度量聚合,輸出數(shù)字類型的值,聚合輸出一個數(shù)字指標(biāo)的為單值數(shù)字型度量聚合;輸出多指標(biāo)的為多值數(shù)字型度量聚合。

1.1、平均值聚合

平均值聚合是一個單值度量聚合,計算從聚合的文檔中提取數(shù)字型值的平均值。
示例1:

GET /city/_doc/_search
{
  "aggs":{
    "avg_population":{"avg":{"field":"population"}}
  }
}

示例2:基于腳本

GET /city/_doc/_search
{
  "aggs":{
    "avg_population":{"avg":{"script":"doc['population'].value + 1000"}}
  }
}

示例3:默認(rèn)值

GET /city/_doc/_search
{
  "aggs":{
    "avg_population":{
      "avg":{
        "field":"population",
        "missing":100
      }
    }
  }
}

1.2、基數(shù)聚合

基數(shù)聚合是一個單值度量聚合,計算不同值的近似計數(shù),值可以從特定字段提取或通過腳本生成。
示例:

GET /people/_doc/_search
{
  "query":{
    "match":{"country":"中國"}
  },
  "aggs":{
    "country_count":{"cardinality":{"field":"country","precision_threshold":100}}
  }
}

1.3、最大值聚合

此聚合為單值聚合,記錄和返回從聚合的文檔中提取的數(shù)字型值中的最大值,值可以從特定字段提取或通過腳本生成。
示例:

GET /city/_doc/_search
{
  "aggs":{
    "max_population":{"max":{"field":"population"}}
  }
}

1.4、最小值聚合

此聚合為單值聚合,記錄和返回從聚合的文檔中提取的數(shù)字型值中的最小值,值可以從特定字段提取或通過腳本生成。
示例:

GET /city/_doc/_search
{
  "aggs":{
    "min_population":{"min":{"field":"population"}}
  }
}

1.5、和聚合

此聚合為單值聚合,其對聚合文檔中提取的數(shù)值型值進(jìn)行求和,值可以從特定字段提取或通過腳本生成。
示例:

GET /city/_doc/_search
{
  "aggs":{
    "sum_population":{"sum":{"field":"population"}}
  }
}

1.6、值計數(shù)聚合

此聚合為單值聚合,其對聚合文檔中提取的值進(jìn)行計數(shù),值可以從特定字段提取或通過腳本生成。
示例:

GET /city/_doc/_search
{
  "aggs":{
    "population_count":{"value_count":{"field":"population"}}
  }
}

1.7、統(tǒng)計聚合

此聚合為多值聚合,其對聚合文檔中提取的數(shù)值型值進(jìn)行統(tǒng)計計算,值可以從特定字段提取或通過腳本生成。統(tǒng)計值包含:最小值,最大值,和,平均值,計數(shù)值。
示例:

GET /city/_doc/_search
{
  "aggs":{
    "population_stats":{"stats":{"field":"population"}}
  }
}

1.8、百分比聚合

此聚合是個多值聚合,對聚合文檔中的數(shù)值型計算一個或多個百分比,我們可以通過百分比聚合結(jié)果評估數(shù)據(jù)分布,判斷數(shù)據(jù)是否符合預(yù)期等。默認(rèn)百分比為:[1,5,25,50,75,95,99]。
示例:

GET /city/_doc/_search
{
  "aggs":{
    "population_liner":{"percentiles":{"field":"population"}}
  }
}

1.9、百分比分級聚合

此聚合為多值聚合,對聚合文檔中的數(shù)值型計算一個或多個級別的百分比。
示例:

GET /city/_doc/_search
{
  "aggs":{
    "population_rank":{"percentile_ranks":{"field":"population","values":[1000,2000]}}
  }
}

1.10、地理邊界聚合

此聚合是一個度量聚合,為字段計算包含所有地點點值的邊界框。
示例:

GET /city/_doc/_search
{
  "query":{
    "match":{"country":"中國"}
  },
  "aggs":{
    "viewport":{"geo_bounds":{"field":"location"}}
  }
}

1.11、地理重心聚合

此聚合為度量聚合,從文檔中的地理點數(shù)據(jù)中獲取所有坐標(biāo)值找那個計算出有力的矩心。
示例:

GET /city/_doc/_search
{
  "query":{
    "match":{"country":"中國"}
  },
  "aggs":{
    "center":{"geo_centroid":{"field":"location"}}
  }
}

2、分組聚合

2.1、直方圖聚合

此聚合為多分組聚合,可以應(yīng)用于從文檔中提取數(shù)值,并在數(shù)值上動態(tài)創(chuàng)建固定大小的分組。
示例:

GET /city/_doc/_search
{
  "aggs":{
    "population_hist":{"histogram":{"field":"population","interval":500}}
  }
}

最小文檔計數(shù):
默認(rèn)情況響應(yīng)會用空分組填補直方圖中的空白,可以利用min_doc_count設(shè)置類修改分組,要求一個更高的最低計數(shù)。
示例:

GET /city/_doc/_search
{
  "aggs":{
    "population_hist":{"histogram":{"field":"population","interval":500,"min_doc_count":1}}
  }
}

分組起始結(jié)束值:
分組默認(rèn)的起始/結(jié)束數(shù)值為所有命中文檔對應(yīng)值的最小值/最大值,但有時我們需要的是一個自定義的范圍。此時可通過extended_bounds進(jìn)行設(shè)置,強制直方圖的聚合從給定的最小值/最大值進(jìn)行分組。當(dāng)extended_bounds.min比文檔最小值大的時候,依然使用文檔的最小值,當(dāng)extended_bounds.max比文檔最大值小的時候,依然使用文檔的最大值。
示例:
GET /city/_doc/_search
{
"aggs":{
"population_hist":{"histogram":{"field":"population","interval":500,"extended_bounds":{"min":1000,"max":5000}}}
}
}

排序:
分組默認(rèn)按照鍵升序排序,可以通過order設(shè)置來控制排序行為。

GET /city/_doc/_search
{
  "aggs":{
    "population_hist":{
      "histogram":{
        "field":"population",
        "interval":500,
        "extended_bounds":{"min":1000,"max":5000},
        "order":{"_key":"desc"}
        
      }
      
    }
  }
}


GET /city/_doc/_search
{
  "aggs":{
    "population_hist":{
      "histogram":{
        "field":"population",
        "interval":500,
        "extended_bounds":{"min":1000,"max":5000},
        "order":{"_count":"desc"}
        
      }
      
    }
  }
}

2.2、日期直方圖聚合

日期直方圖聚合是一個多分組聚合,是專門應(yīng)用于日期類型的直方圖。
示例:

GET /people/_doc/_search
{
  "aggs":{
    "date_over_time":{
      "date_histogram":{
        "field":"date",
        "interval":"month",
        "format":"yyyy-mm-dd"
      }
    }
  }
}

2.3、時間范圍聚合

此聚合專門用于時間型數(shù)據(jù)的范圍聚合,其form和to參數(shù)可以指定日期或日期數(shù)學(xué)表達(dá)式,同時可指定form和to的日期格式,時間范圍包含from但排除同。
示例:

GET /people/_doc/_search
{
  "aggs":{
    "date_range":{
      "date_range":{
        "field":"date",
        "format":"yyyy-mm-dd",
        "ranges":{
          "from":"2010-01-01",
          "to":"2012-12-30"
        }
      }
    }
  }
}

2.4、范圍聚合

此聚合基于多組范圍值來聚合,可設(shè)定一系列范圍,每個范圍代表一個分組,文檔值會檢查每個分組范圍,并使相關(guān)文檔落入分組中。
示例:

GET /city/_doc/_search
{
  "aggs":{
    "popu_range":{
      "range":{
        "field":"population",
        "ranges":[
          {"from":0,"to":500},
          {"from":500,"to":1000},
          {"from":1000,"to":2000},
          {"from":2000,"to":3000}
          ]
      }
    }
  }
}

2.5、過濾聚合

此聚合是單分組聚合,包含文檔集中所有匹配指定的過濾條件的文檔。
示例:

GET /city/_doc/_search
{
  "aggs":{
    "population_china":{
      "filter":{
        "match":{"country":"中國"}
      },
      "aggs":{
          "pupo_avg":{
            "avg":{"field":"population"}
          }
        }
    }
  }
}

2.6、多重過濾聚合

此聚合定義多分組聚合,每個分組關(guān)聯(lián)一個過濾條件,并收集所有滿足自身過濾條件的文檔??梢蕴砑觨ther_buket設(shè)置其他分組是否參與分組,并通過other_bucket_key設(shè)置其他分組的名稱。
示例:

GET /city/_doc/_search
{
  "aggs":{
    "population_china":{
      "filters":{
        "other_bucket_key":"other_msg",
        "filters":{
          "country":{"match":{"country":"中國"}},
          "descirbe":{"match":{"describe":"中國"}}
        }
      },
      "aggs":{
          "pupo_avg":{
            "avg":{"field":"population"}
          }
        }
    }
  }
}

2.7、空值聚合

此聚合是一個基于字段數(shù)據(jù)的分組聚合,在當(dāng)前文檔集中對所有缺失字段值的文檔創(chuàng)建一個分組,這個聚合通常和其他字段數(shù)據(jù)分組聚合一起使用,返回由于缺少字段值而不能放入其他任何分組中的所有文檔的信息。
示例:

GET /city/_doc/_search
{
  "aggs":{
    "population_stats":{"missing":{"field":"population"}}
  }
}

2.8、地理點距離聚合

作用于地理點類型字段上的多組聚合,原理同范圍聚合類似,可以設(shè)定一個圓點和一系列距離范圍分組。聚合評估每個文檔的值和原點之間的距離,然后基于范圍決定文檔屬于哪個分組。
示例:

GET /city/_doc/_search
{
  "aggs":{
    "city_dist":{
      "geo_distance":{
        "field":"location",
        "origin":"39.1233,116.2424",
        "ranges":[
          {"to":1000},
          {"from":1000,"to":5000},
          {"to":10000}
        ]
    
      }
    }
  }
}

3、管道聚合

管道聚合工作與其他聚合的輸出結(jié)果而不是文檔集,用于向輸出樹添加信息,通過bucket_path參數(shù)指定請求的路徑來引用數(shù)據(jù)的來源。管道聚合不能擁有子聚合,但可以在bucket_path參數(shù)中引入另一個管道聚合,使管道聚合連接起來。
管道聚合分類:

  • 父類聚合:在父聚合輸出的基礎(chǔ)上進(jìn)行管道聚合,可以在現(xiàn)有分組的基礎(chǔ)上計算新的分組或聚合。
  • 兄弟聚合:在兄弟聚合輸出結(jié)果的基礎(chǔ)上進(jìn)行管道聚合,可以計算與兄弟聚合相同等級的新聚合。

bucket_path語法:

  • 聚合分隔符為“>”;
  • 指標(biāo)分隔符為".";
  • 聚合名為<聚合名稱>;
  • 指標(biāo)為<指標(biāo)的名稱>;
  • 路徑為:<聚合名>[<聚合分隔符><聚合名>]*[<指標(biāo)分隔符><指標(biāo)>]

特殊路徑:
bucket_path可以使用特殊路徑如“_count”,讓管道聚合使用文檔計數(shù)作為輸入?yún)?shù)。

3.1、平均分組聚合

此聚合會計算在一組聚合中指定指標(biāo)的平均值,指定的指標(biāo)必須是數(shù)字型而且這組聚合必須是多組聚合。
參數(shù):

  • bucket_path:要計算平均值的分組路徑;
  • gap_policy:當(dāng)數(shù)據(jù)缺口出現(xiàn)時應(yīng)用的策略(默認(rèn)跳過);
  • format:規(guī)范聚合輸出的格式(默認(rèn)為null);

示例:

GET /people/_doc/_search
{
  "aggs":{
    "country_term":{
      "terms":{"field":"country"},
      "aggs":{
        "age_avg":{"avg":{"field":"age"}}
      }
    },
    "avg_country_popu":{
      "avg_bucket":{"buckets_path":"country_term>age_avg"}
    }
  }
}

3.2、移動平均聚合

對一組有序的數(shù)據(jù),移動平均聚合會在數(shù)據(jù)上滑動一個固定大小的窗口并給出窗口的平均值。
參數(shù):

  • buckets_path:指標(biāo)路徑(必填);
  • model:移動平均加權(quán)模型;
  • gap_policy:數(shù)據(jù)缺口時的行為(默認(rèn)插入零);
  • window:在直方圖上滑動的窗口大?。J(rèn)為5);
  • settings:模型的具體設(shè)置,根據(jù)指定的模型有不同的內(nèi)容;

示例:

GET /people/_doc/_search
{
 "aggs":{
    "date_over_time":{
      "date_histogram":{
        "field":"date",
        "interval":"month",
        "format":"yyyy-mm-dd"
      },
      "aggs":{
        "age_sum":{"sum":{"field":"age"}},
        "age_moving":{
          "moving_avg":{
            "buckets_path":"age_sum",
            "model":"holt",
            "window":5,
            "gap_policy":"insert_zeros",
            "settings":{"alpha":0.8}
        }
        
      }
    }
  }
  }
}

3.3、總和分組聚合

計算所有分組中指定指標(biāo)的和。
示例:

GET /people/_doc/_search
{
  "aggs":{
    "country_term":{
      "terms":{"field":"country"}
      },
      
    "sum_country":{
     "sum_bucket":{"buckets_path":"country_term._count"}
    }
  }
}

3.4、最大/小分組聚合

獲取一組聚合指標(biāo)中的最大/小值。
示例:

GET /people/_doc/_search
{
  "aggs":{
    "country_count":{
      "terms":{"field":"country"},
      "aggs":{
        "avg_age":{
          "avg":{"field":"age"}
        }
      }
    },
      
    "max_avg_age":{
     "max_bucket":{"buckets_path":"country_count>avg_age"}
    },
    "min_avg_age":{
     "min_bucket":{"buckets_path":"country_count>avg_age"}
    }
  }
}

3.5、統(tǒng)計分組聚合

統(tǒng)計所有分組中某個指標(biāo)的各種統(tǒng)計值。
示例:

GET /people/_doc/_search
{
 "aggs":{
    "date_over_time":{
      "date_histogram":{
        "field":"date",
        "interval":"month",
        "format":"yyyy-mm-dd"
      },
      "aggs":{
        "age_avg":{"avg":{"field":"age"}}
    }
  },
  "avg_stat":{
    "stats_bucket":{"buckets_path":"date_over_time>age_avg"}
  }
  }
}

3.6、百分位分組聚合

在所有分組中對指定的指標(biāo)計算百分比。
示例:

GET /people/_doc/_search
{
 "aggs":{
    "country_term":{
      "terms":{"field":"country"  },
      "aggs":{
        "age_avg":{
          "avg":{"field":"age"}
        }
      }
    },
    
    "percent_age":{
      "percentiles_bucket":{"buckets_path":"country_term>age_avg"}
    }
  }
}

4、DocValue

DocValue原理:
聚合的場景是遍歷文檔,并收集對應(yīng)字段的唯一詞項,對這些詞項做聚合處理。而使用倒排索引做這件事情代價會很高。DocValue是倒排索引的轉(zhuǎn)置,其保存的是文檔與其包含的詞項的映射。這個數(shù)據(jù)結(jié)構(gòu)可以使聚合更快、更高效并且內(nèi)存友好。
DocValue是在索引時與倒排索引同時創(chuàng)建的,其也是基于段生成并不可改變,并會被序列化存儲到磁盤中。我們可以充分利用操作系統(tǒng)的內(nèi)存,而不是 JVM 的 Heap 。 當(dāng) working set 遠(yuǎn)小于系統(tǒng)的可用內(nèi)存,系統(tǒng)會自動將 Doc Values 駐留在內(nèi)存中,使得其讀寫十分快速;不過,當(dāng)其遠(yuǎn)大于可用內(nèi)存時,系統(tǒng)會根據(jù)需要從磁盤讀取 Doc Values,然后選擇性放到分頁緩存中。很顯然,這樣性能會比在內(nèi)存中差很多,但是它的大小就不再局限于服務(wù)器的內(nèi)存了。

DocValue存儲:
因為 Doc Values 不是由 JVM 來管理,所以 Elasticsearch 實例可以配置一個很小的 JVM Heap,這樣給系統(tǒng)留出來更多的內(nèi)存。同時更小的 Heap 可以讓 JVM 更加快速和高效的回收。之前,我們會建議分配機器內(nèi)存的 50% 來給 JVM Heap。但是對于 Doc Values,這樣可能不是最合適的方案了。 以 64gb 內(nèi)存的機器為例,可能給 Heap 分配 4-16gb 的內(nèi)存更合適,而不是 32gb。
Doc Values 本質(zhì)上是一個序列化的 列式存儲,這種存儲方式也非常便于壓縮,特別是數(shù)字類型。這樣可以減少磁盤空間并且提高訪問速度。

DocValue啟用:
Doc Values 默認(rèn)對所有字段啟用,除了 analyzed strings。也就是說所有的數(shù)字、地理坐標(biāo)、日期、IP 和不分析( not_analyzed )字符類型都會默認(rèn)開啟。故可以對這些字段很高效的聚合和排序操作,當(dāng)確定某些字段不會用于聚合或排序等操作,可以禁用DocValue,這樣不僅節(jié)約磁盤,也會提升索引的速度。
要禁用 Doc Values ,在字段的映射(mapping)設(shè)置 doc_values: false 即可。

5、分析字符串和FieldData

Doc values 不支持 analyzed 字符串字段,因為它們不能很有效的表示多值字符串。 Doc values 最有效的是,當(dāng)每個文檔都有一個或幾個 tokens 時, 但不是無數(shù)的,分析字符串(想象一個 PDF ,可能有幾兆字節(jié)并有數(shù)以千計的獨特 tokens)。
與 doc values 不同,fielddata 構(gòu)建和管理 100% 在內(nèi)存中,常駐于 JVM 內(nèi)存堆。這意味著它本質(zhì)上是不可擴展的,有很多邊緣情況下要提防。
避免分析字段的另外一個原因就是:高基數(shù)字段在加載到 fielddata 時會消耗大量內(nèi)存。 分析的過程會經(jīng)常(盡管不總是這樣)生成大量的 token,這些 token 大多都是唯一的。 這會增加字段的整體基數(shù)并且?guī)砀蟮膬?nèi)存壓力。
一旦分析字符串被加載到 fielddata ,他們會一直在那里,直到被驅(qū)逐(或者節(jié)點崩潰)。由于這個原因,留意內(nèi)存的使用情況,了解它是如何以及何時加載的,怎樣限制對集群的影響是很重要的。
Fielddata 是 延遲 加載。如果你從來沒有聚合一個分析字符串,就不會加載 fielddata 到內(nèi)存中。此外,fielddata 是基于字段加載的, 這意味著只有很活躍地使用字段才會增加 fielddata 的負(fù)擔(dān)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容