自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一起學(xué) Elasticsearch 系列-聚合查詢

大數(shù)據(jù) 開發(fā)
聚合查詢是 Elasticsearch 中一種強(qiáng)大的數(shù)據(jù)分析工具,用于從索引中提取和計(jì)算有關(guān)數(shù)據(jù)的統(tǒng)計(jì)信息。

聚合查詢是 Elasticsearch 中一種強(qiáng)大的數(shù)據(jù)分析工具,用于從索引中提取和計(jì)算有關(guān)數(shù)據(jù)的統(tǒng)計(jì)信息。聚合查詢可以執(zhí)行各種聚合操作,如計(jì)數(shù)、求和、平均值、最小值、最大值、分組等,以便進(jìn)行數(shù)據(jù)匯總和分析。

下面是一些常見的聚合查詢類型:

  • Metric Aggregations(指標(biāo)聚合):這些聚合操作返回基于字段值的度量結(jié)果,如求和、平均值、最小值、最大值等。常見的指標(biāo)聚合包括 Sum、Avg、Min、Max、Stats 等。
  • Bucket Aggregations(桶聚合):類比SQL中的group by,主要用于統(tǒng)計(jì)不同類型數(shù)據(jù)的數(shù)量,這些聚合操作將文檔劃分為不同的桶(buckets),并對(duì)每個(gè)桶中的文檔進(jìn)行聚合計(jì)算。常見的桶聚合包括 Terms(按字段值分組)、Date Histogram(按時(shí)間間隔分組)、Range(按范圍分組)等。
  • Pipeline Aggregations(管道聚合):這些聚合操作通過在其他聚合結(jié)果上執(zhí)行額外的計(jì)算來產(chǎn)生新的聚合結(jié)果。例如,使用 Moving Average 聚合可以計(jì)算出移動(dòng)平均值。

聚合查詢通常與查詢語句結(jié)合使用,可以在查詢結(jié)果的基礎(chǔ)上進(jìn)行進(jìn)一步的數(shù)據(jù)分析和統(tǒng)計(jì)。聚合查詢語法使用 JSON 格式,可以通過 Elasticsearch 的 REST API 或各種客戶端庫進(jìn)行發(fā)送和解析。

聚合查詢支持嵌套,即一個(gè)聚合內(nèi)部可以包含別的子聚合,從而實(shí)現(xiàn)非常復(fù)雜的數(shù)據(jù)挖掘和統(tǒng)計(jì)需求。

在ES中,用于進(jìn)行聚合的字段可以是exact value也可以是分詞字段,對(duì)于分詞字段,可以使用特定的聚合操作來進(jìn)行分組聚合,例如Terms Aggregation、Date Histogram Aggregation等。

對(duì)于text字段的聚合,可以通過開啟fielddata來實(shí)現(xiàn),但通常不建議這樣做,因?yàn)閒ielddata會(huì)將聚合使用的數(shù)據(jù)結(jié)構(gòu)從磁盤(doc_values)轉(zhuǎn)換為堆內(nèi)存(field_data),在處理大量數(shù)據(jù)時(shí)容易導(dǎo)致內(nèi)存溢出(OOM)問題。

如果需要在text字段上執(zhí)行聚合,可以考慮在該字段上添加.keyword子字段,并使用該子字段進(jìn)行聚合操作,以獲得更準(zhǔn)確的結(jié)果。

doc_values & fielddata

在 Elasticsearch 中,聚合操作主要依賴于 doc_values 或 fielddata 來進(jìn)行。

  • Doc Values(文檔值):Doc Values 是一種以列式存儲(chǔ)格式保存字段值的數(shù)據(jù)結(jié)構(gòu),它用于支持快速的聚合、排序和統(tǒng)計(jì)操作。Doc Values 在磁盤上存儲(chǔ),并被加載到 JVM 堆內(nèi)存中進(jìn)行計(jì)算。它們適用于精確值(如 keyword 類型)和數(shù)字類型的字段,在大多數(shù)情況下是默認(rèn)啟用的。
  • Fielddata(字段數(shù)據(jù)):Fielddata 是一種將字段值加載到堆內(nèi)存中的數(shù)據(jù)結(jié)構(gòu),它用于支持復(fù)雜的文本分析和聚合操作。Fielddata 適用于文本類型的字段,例如 text 類型,因?yàn)樗鼈冃枰M(jìn)行分詞和分析。但是,由于 Fielddata 需要大量的堆內(nèi)存資源,特別是在處理大數(shù)據(jù)集時(shí),容易導(dǎo)致內(nèi)存溢出(OOM)的問題,因此不建議隨意啟用。

在設(shè)計(jì)索引時(shí),需要根據(jù)字段類型和使用場景的不同,合理選擇是否啟用 Doc Values 或 Fielddata,以平衡性能和資源消耗的需求。

當(dāng)執(zhí)行聚合操作時(shí),Elasticsearch 需要訪問所有匹配文檔的字段值。對(duì)于非文本字段,默認(rèn)情況下Elasticsearch 使用 doc values 來實(shí)現(xiàn)。對(duì)于文本字段,必須首先啟用 fielddata。然而,由于 fielddata 占用大量內(nèi)存,Elasticsearch 默認(rèn)禁用了它。

如果你確實(shí)需要對(duì)一個(gè)文本字段啟用 fielddata(雖然大多數(shù)場景下不推薦這么做,因?yàn)榭赡軐?dǎo)致內(nèi)存消耗過大),你可以通過更新映射(mapping)來實(shí)現(xiàn)。

以下是如何在 my_field 字段上啟用 fielddata 的示例:

PUT my_index/_mapping

{
  "properties": {
    "my_field": { 
      "type":     "text",
      "fielddata": true
    }
  }
}

注意:更改 fielddata 設(shè)置只會(huì)影響新的數(shù)據(jù),已經(jīng)索引的數(shù)據(jù)不會(huì)受到更改。如果你想讓更改生效,需要重新索引(reindex)你的數(shù)據(jù)

另外,一般情況下,建議使用 mapping 中的 keyword 類型來進(jìn)行聚合、排序或腳本,而不是啟用 text 類型的 fielddata。這是因?yàn)?nbsp;keyword 類型字段默認(rèn)開啟了 doc values,比在 text 上啟用 fielddata 更加高效且節(jié)省內(nèi)存。

multi-fields

在 Elasticsearch 中,一個(gè)字段有可能是 multi-fields(多字段)類型,這意味著同一份數(shù)據(jù)可以被索引為不同類型的字段。常見的情況就是,一個(gè)字段既被索引為 text 類型用于全文搜索,又被索引為 keyword 類型用于精確值搜索、排序和聚合。

當(dāng)你在一個(gè)字段名后面加上 .keyword(例如 field.keyword),這說明你是在引用這個(gè)字段的 keyword 子字段。這個(gè) keyword 子字段在索引時(shí)并不會(huì)被分詞器拆分成單獨(dú)的詞條,而是作為一個(gè)完整的字符串被存儲(chǔ)。這樣,你就可以對(duì)這個(gè)字段進(jìn)行精確值匹配、排序或者聚合操作。

舉例來說,如果你有一個(gè) message 字段并且想要對(duì)其進(jìn)行聚合,你應(yīng)該使用 message.keyword 而非 message。因?yàn)槿绻阒苯訉?duì) message 進(jìn)行聚合,Elasticsearch 就會(huì)嘗試對(duì)每一個(gè)獨(dú)立的詞條進(jìn)行聚合,而不是對(duì)整個(gè)字段值進(jìn)行聚合。

如果你的字段沒有 .keyword 子字段,那可能是在定義 mapping 時(shí)沒有包含這一部分,或者這個(gè)字段的類型本身就是 keyword。

分桶聚合

分桶(Bucket)聚合是一種特殊類型的聚合,它將輸入文檔集合中的文檔分配到一個(gè)或多個(gè)桶中,每個(gè)桶都對(duì)應(yīng)于一個(gè)鍵(key)。

下面是一些常用的分桶聚合類型:

  • terms:基于文檔中某個(gè)字段的值,將文檔分組到各個(gè)桶中。
  • date_histogram:基于日期字段,將文檔按照指定的時(shí)間間隔分組到各個(gè)桶中。
  • histogram:基于數(shù)值字段,將文檔按照指定的數(shù)值范圍分組到各個(gè)桶中。
  • range:根據(jù)設(shè)置的范圍,將數(shù)據(jù)分為不同的桶。

以下是一個(gè)使用 terms 分桶聚合的例子:

假設(shè)你有一個(gè)包含博客文章的 blog 索引,你想知道每個(gè)作者寫了多少篇文章,可以使用以下查詢:

GET /blog/_search
{
  "size": 0,
  "aggs": {
    "authors": {
      "terms": { "field": "author.keyword" }
    }
  }
}

在這個(gè)查詢中:

  • size: 0 表示我們只對(duì)聚合結(jié)果感興趣,不需要返回任何具體的搜索結(jié)果。
  • "aggs" (或者 "aggregations") 塊定義了我們的聚合。
  • "authors" 是我們自己為這個(gè)聚合命名的標(biāo)簽,你可以用任何你喜歡的標(biāo)簽名。
  • "terms": { "field": "author.keyword" } 定義了我們要進(jìn)行聚合的方式和字段。這里,我們告訴 Elasticsearch 使用 terms 聚合,并且使用 author.keyword 字段的值作為分桶的依據(jù)。

Elasticsearch 將返回一個(gè)包含每個(gè)作者以及他們所寫的文章數(shù)量的列表。注意,由于 Elasticsearch 默認(rèn)只返回前十個(gè)桶,如果你的數(shù)據(jù)中有更多的作者,可能需要設(shè)置 size 參數(shù)來獲取更多的結(jié)果。

Histogram

histogram 是桶聚合的一種類型,它可以按照指定的間隔將數(shù)字字段的值劃分為一系列桶。每個(gè)桶代表了這個(gè)區(qū)間內(nèi)的所有文檔。

以下是一個(gè)例子,我們根據(jù)價(jià)格字段創(chuàng)建一個(gè)間隔為 50 的直方圖:

GET /products/_search
{
  "size": 0,
  "aggs" : {
    "prices" : {
      "histogram" : {
        "field" : "price",
        "interval" : 50
      }
    }
  }
}

在這個(gè)例子中,“prices” 是一個(gè) histogram 聚合,它以 50 為間隔將產(chǎn)品的價(jià)格劃分為一系列的桶。

指標(biāo)聚合

在 Elasticsearch 中,指標(biāo)聚合是對(duì)數(shù)據(jù)進(jìn)行統(tǒng)計(jì)計(jì)算的一種方式,例如求和、平均值、最小值、最大值等。以下是一些常用的指標(biāo)聚合類型:

  • avg:計(jì)算字段的平均值。
  • sum:計(jì)算字段的總和。
  • min:查找字段的最小值。
  • max:查找字段的最大值。
  • count:計(jì)算匹配文檔的數(shù)量。
  • stats:提供了 count、sum、min、max 和 avg 的基本統(tǒng)計(jì)。

下面是一個(gè)示例,假設(shè)我們有一個(gè)包含售賣商品的 “sales” 索引,我們想要知道所有銷售記錄中的平均價(jià)格,可以使用 avg 聚合如下操作:

GET /sales/_search
{
  "size": 0,
  "aggs": {
    "average_price": {
      "avg": { "field": "price" }
    }
  }
}

Percentiles

percentiles 是指標(biāo)聚合的一種,它用于計(jì)算數(shù)值字段的百分位數(shù)。給定一個(gè)列表百分比,Elasticsearch 可以計(jì)算每個(gè)百分比下的數(shù)值。

以下是一個(gè)例子,我們計(jì)算價(jià)格字段的 1st, 5th, 25th, 50th, 75th, 95th, and 99th 百分位數(shù):

GET /products/_search
{
  "size": 0,
  "aggs" : {
    "price_percentiles" : {
      "percentiles" : {
        "field" : "price",
        "percents" : [1, 5, 25, 50, 75, 95, 99]
      }
    }
  }
}

在這個(gè)例子中,“price_percentiles” 是一個(gè) percentiles 聚合,它計(jì)算了價(jià)格在各個(gè)百分位點(diǎn)的數(shù)值。

注意,對(duì)于大數(shù)據(jù)集,計(jì)算精確的百分位數(shù)可能需要消耗大量資源。因此,Elasticsearch 默認(rèn)使用一個(gè)名為 TDigest 的算法來提供近似的計(jì)算結(jié)果,同時(shí)還能保持內(nèi)存使用的可控性。

cardinality

如果你想在 Elasticsearch 中進(jìn)行去重操作,可以使用 terms 聚合加上 cardinality 聚合。這是一個(gè)示例,假設(shè)我們有一個(gè)包含user_id的 "users" 索引,并且我們想要知道有多少唯一的 user_id:

GET /users/_search
{
  "size": 0,
  "aggs": {
    "distinct_user_ids": {
      "cardinality": {
        "field": "user_id.keyword"
      }
    }
  }
}

在這個(gè)查詢中:

  • "distinct_user_ids" 是我們自己為這個(gè)聚合命名的標(biāo)簽。
  • "cardinality": { "field": "user_id.keyword" } 使用了 cardinality 聚合,該聚合會(huì)返回指定字段(在這里是 user_id.keyword)的不同值的數(shù)量。

Elasticsearch 將返回一個(gè)結(jié)果,告訴我們有多少個(gè)不同的 user_id。請(qǐng)注意,cardinality 聚合可能并不總是完全精確,特別是對(duì)于大型數(shù)據(jù)集,因?yàn)樗趦?nèi)部使用了一種叫做 HyperLogLog 的算法來近似計(jì)算基數(shù),這種算法會(huì)在保持內(nèi)存消耗相對(duì)較小的情況下提供接近準(zhǔn)確的結(jié)果。如果你需要完全精確的結(jié)果,可能需要考慮其他方法,例如使用腳本或者將數(shù)據(jù)導(dǎo)出到外部系統(tǒng)進(jìn)行處理。

管道聚合

在 Elasticsearch 中,管道聚合(pipeline aggregations)是指這樣一種聚合:它以其他聚合的結(jié)果作為輸入,并進(jìn)行進(jìn)一步處理。

常見的管道聚合包括:

  • avg_bucket
  • sum_bucket
  • min_bucket
  • max_bucket
  • stats_bucket
  • extended_stats_bucket
  • percentiles_bucket

這些都是 bucket 級(jí)別的管道聚合,它們會(huì)在一組數(shù)據(jù)桶上操作。

下面給出一個(gè)示例,假設(shè)我們有一個(gè)銷售記錄索引 "sales",每個(gè)銷售記錄都有售價(jià) "price" 和銷售日期 "date" 字段。如果我們想要計(jì)算每月平均銷售價(jià)格,并找出所有月份中平均價(jià)格最高的月份,可以使用 date_histogram 聚合加上 avg 以及 max_bucket 聚合來實(shí)現(xiàn):

GET /sales/_search
{
  "size": 0,
  "aggs": {
    "sales_per_month": {
      "date_histogram": {
        "field": "date",
        "calendar_interval": "month"
      },
      "aggs": {
        "avg_price": {
          "avg": { "field": "price" }
        }
      }
    },
    "max_avg_price": {
      "max_bucket": {
        "buckets_path": "sales_per_month>avg_price"
      }
    }
  }
}

在這個(gè)查詢中:

  • "sales_per_month" 是一個(gè)按月聚合銷售記錄的 date_histogram 聚合。
  • "avg_price" 是一個(gè)嵌套在 "sales_per_month" 下的 avg 聚合,用于計(jì)算每月的平均銷售價(jià)格。
  • "max_avg_price" 是一個(gè) max_bucket 聚合,它會(huì)找出 "sales_per_month" 中所有子桶的 "avg_price" 最大值。

注意到 "max_avg_price" 中的 "buckets_path": "sales_per_month>avg_price"。buckets_path 參數(shù)指定了此管道聚合的輸入來源,> 符號(hào)表示路徑層次,即先取 "sales_per_month" 聚合的結(jié)果,再取其中的 "avg_price" 聚合的結(jié)果作為輸入。

返回的結(jié)果中會(huì)包含每個(gè)月的平均銷售價(jià)格,以及所有月份中平均銷售價(jià)格的最大值。

嵌套聚合

嵌套聚合就是在聚合內(nèi)使用聚合,在 Elasticsearch 中,嵌套聚合通常用于處理 nested 類型的字段。nested 類型允許你將一個(gè)文檔中的一組對(duì)象作為獨(dú)立的文檔進(jìn)行索引和查詢,這對(duì)于擁有復(fù)雜數(shù)據(jù)結(jié)構(gòu)(例如數(shù)組或列表中的對(duì)象)的場景非常有用。

假設(shè)我們有一個(gè) users 索引,每個(gè) user 文檔都有一個(gè) purchases 字段,該字段是一個(gè)列出用戶所有購買記錄的數(shù)組,每個(gè)購買記錄包含 product_id 和 price。如果我們想要找出價(jià)格超過 100 的所有產(chǎn)品的 ID,可以使用 nested 聚合:

GET /users/_search
{
  "size": 0,
  "aggs": {
    "all_purchases": {
      "nested": {
        "path": "purchases"
      },
      "aggs": {
        "expensive_purchases": {
          "filter": { "range": { "purchases.price": { "gt": 100 } } },
          "aggs": {
            "product_ids": { "terms": { "field": "purchases.product_id" } }
          }
        }
      }
    }
  }
}

在這個(gè)查詢中:

  • "all_purchases" 是一個(gè) nested 聚合,指定了 nested 對(duì)象的路徑 purchases。
  • "expensive_purchases" 是一個(gè)嵌套在 "all_purchases" 下的 filter 聚合,它會(huì)過濾出 price 大于 100 的購買記錄。
  • "product_ids" 是一個(gè)嵌套在 "expensive_purchases" 下的 terms 聚合,它會(huì)提取出所有滿足條件的 product_id。

返回的結(jié)果將包含所有 price 大于 100 的產(chǎn)品的 ID 列表。

請(qǐng)注意,在處理 nested 數(shù)據(jù)時(shí),你需要確保 mapping 中相應(yīng)的字段已經(jīng)被設(shè)置為 nested 類型,否則該查詢可能無法按預(yù)期工作。

基于查詢結(jié)果的聚合 & 基于聚合結(jié)果的查詢

基于查詢結(jié)果的聚合:在這種情況下,我們首先執(zhí)行一個(gè)查詢,然后對(duì)查詢結(jié)果進(jìn)行聚合。

例如,如果我們要查詢所有包含某關(guān)鍵字的文檔,并計(jì)算它們的平均價(jià)格,可以這樣做:

GET /products/_search
{
  "query": {
    "match": {
      "description": "laptop"
    }
  },
  "aggs": {
    "average_price": {
      "avg": {
        "field": "price"
      }
    }
  }
}

在上述例子中,我們首先通過 match 查詢找到描述中包含 "laptop" 的所有產(chǎn)品,然后對(duì)這些產(chǎn)品的價(jià)格進(jìn)行平均值聚合。

基于聚合結(jié)果的查詢:這種情況下,我們先執(zhí)行聚合,然后基于聚合的結(jié)果執(zhí)行過濾操作。

這通常用于在聚合結(jié)果中應(yīng)用一些額外的過濾條件。例如,如果我們想對(duì)所有產(chǎn)品進(jìn)行銷售數(shù)量聚合,然后從結(jié)果中過濾出銷售數(shù)量大于10的產(chǎn)品,可以這樣做:

GET /sales/_search
{
  "size": 0,
  "aggs": {
    "sales_per_product": {
      "terms": {
        "field": "product_id"
      }
    }
  },
  "post_filter": {
    "bucket_selector": {
      "buckets_path": {
        "salesCount": "sales_per_product._count"
      },
      "script": {
        "source": "params.salesCount > 10"
      }
    }
  }
}

在上述例子中,我們首先執(zhí)行了一個(gè) terms 聚合,按產(chǎn)品ID匯總銷售記錄。然后我們使用 bucket_selector post-filter 進(jìn)一步篩選出銷售數(shù)量大于10的桶(每個(gè)桶對(duì)應(yīng)一個(gè)產(chǎn)品)。

聚合排序

(1) count

在 Elasticsearch 中,聚合排序允許你基于某一聚合的結(jié)果來對(duì)桶進(jìn)行排序。例如,你可能希望查看銷售量最高的10個(gè)產(chǎn)品,可以使用 terms 聚合以及其 size 和 order 參數(shù)來實(shí)現(xiàn):

GET /sales/_search

{
  "size": 0,
  "aggs": {
    "top_products": {
      "terms": {
        "field": "product_id",
        "size": 10,
        "order": { "_count": "desc" }
      }
    }
  }
}

在這個(gè)例子中,top_products 是一個(gè) terms 聚合,用于按 product_id 對(duì)銷售記錄進(jìn)行分組。

"size": 10 的意思是只返回銷售量最高的前10個(gè)產(chǎn)品(即只返回前10個(gè)桶)。

"order": { "_count": "desc" } 表示按桶中文檔的數(shù)量(也就是銷售量)降序排序。_count 是一個(gè)內(nèi)置的排序鍵,代表桶中文檔的數(shù)量。

返回的結(jié)果將包含銷售量最高的前10個(gè)產(chǎn)品的 ID 列表。

(2) term

_term 在 Elasticsearch 的聚合排序中用來指定按照詞條(即桶的鍵)來排序。

GET /sales/_search

{
  "size": 0,
  "aggs": {
    "products": {
      "terms": {
        "field": "product_id",
        "order": { "_term": "asc" }
      }
    }
  }
}

在這個(gè)例子中,通過 "order": { "_term": "asc" } 指定了按照 product_id 的值升序排序這些桶。

返回的結(jié)果將包含按照 product_id 升序排列的產(chǎn)品 ID 列表,每個(gè)產(chǎn)品 ID 對(duì)應(yīng)一個(gè)桶,并且每個(gè)桶內(nèi)包含對(duì)應(yīng)產(chǎn)品的銷售記錄。

需要注意的是,在新版本的 Elasticsearch 中(7.0 以后),_term 已經(jīng)被 key 替代用于排序。

GET /sales/_search

{
  "size": 0,
  "aggs" : {
    "products" : {
      "terms" : {
        "field" : "product_id",
        "order" : { "_key" : "asc" }
      }
    }
  }
}
責(zé)任編輯:趙寧寧 來源: Java隨想錄
相關(guān)推薦

2023-11-13 22:27:53

Mapping數(shù)據(jù)庫

2023-11-13 12:48:32

語言DSL

2024-02-28 12:12:20

Pipeline數(shù)據(jù)機(jī)制

2023-12-26 12:12:57

檢索調(diào)優(yōu)Scripting場景

2022-11-29 16:35:02

Tetris鴻蒙

2022-12-02 14:20:09

Tetris鴻蒙

2022-11-14 17:01:34

游戲開發(fā)畫布功能

2023-03-30 09:32:27

2023-02-28 07:28:50

Spritepixijs

2023-04-12 07:46:24

JavaScriptWebGL

2023-03-29 07:31:09

WebGL坐標(biāo)系

2023-04-26 07:42:16

WebGL圖元的類型

2023-05-04 08:48:42

WebGL復(fù)合矩陣

2023-06-26 15:14:19

WebGL紋理對(duì)象學(xué)習(xí)

2025-03-17 11:21:08

APISwagger界面

2023-05-31 20:10:03

WebGL繪制立方體

2023-05-16 07:44:03

紋理映射WebGL

2023-04-13 07:45:15

WebGL片元著色器

2023-04-11 07:48:32

WebGLCanvas

2023-03-02 07:44:39

pixijsWebGL
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)