說明
aggregate 階段會從前一階段傳回的文件計算匯總結果 (例如計數、總和)。
(選用) 如果提供分組運算式,系統會根據提供的運算式將文件分組,然後將累加器函式套用至每個群組。
語法
如要進行不含 group-by 的匯總,aggregate 階段會採用一或多個別名匯總運算式:
Node.js
const cities = await db.pipeline()
.collection("/cities")
.aggregate(
countAll().as("total"),
average("population").as("avg_population")
)
.execute();
如果是使用分組的匯總,除了匯總器之外,還需要額外的群組:
Node.js
const result = await db.pipeline()
.collectionGroup('citites')
.aggregate({
accumulators: [
countAll().as('cities'),
field('population').sum().as('total_popoluation')
],
groups: [field('location.state').as('state')]
})
.execute();
行為
不分組的匯總
建立 cities 集合,並加入下列文件:
Node.js
await db.collection('cities').doc('SF').set({name: 'San Francisco', state: 'CA', country: 'USA', population: 870000});
await db.collection('cities').doc('LA').set({name: 'Los Angeles', state: 'CA', country: 'USA', population: 3970000});
await db.collection('cities').doc('NY').set({name: 'New York', state: 'NY', country: 'USA', population: 8530000});
await db.collection('cities').doc('TOR').set({name: 'Toronto', state: null, country: 'Canada', population: 2930000});
await db.collection('cities').doc('MEX').set({name: 'Mexico City', state: null, country: 'Mexico', population: 9200000});
如要找出城市總數和平均人口數,請按照下列步驟操作:
Node.js
const cities = await db.pipeline()
.collection("/cities")
.aggregate(
countAll().as("total"),
average("population").as("avg_population")
)
.execute();
這會產生:
{avg_population: 5100000, total: 5}
對群組執行匯總作業
提供 groups 引數,即可對每個不同的群組執行匯總作業。
舉例來說,如要找出每個國家/地區和每個州人口最多的城市,請執行下列查詢:
Node.js
const cities = await db.pipeline()
.collection("/cities")
.aggregate({
accumulators: [
countAll().as("number_of_cities"),
maximum("population").as("max_population")
],
groups: ["country", "state"]
})
.execute();
這會提供:
{country: "USA", state: "CA", max_population: 3970000, number_of_cities: 2},
{country: "USA", state: "NY", max_population: 8530000, number_of_cities: 1},
{country: "Canada", state: null, max_population: 2930000, number_of_cities: 1},
{country: "Mexico", state: null, max_population: 9200000, number_of_cities: 1}
分組的複雜運算式
除了依欄位值分組,aggregate 階段也支援依複雜運算式的結果分組。任何在 select 階段有效的運算式,都可以做為分組鍵。這樣一來,您就能根據計算值或條件,彈性分組。
舉例來說,如要依州別欄位是否為空值分組,並找出各組的總人口數,請執行下列操作:
Node.js
const cities = await db.pipeline()
.collection("/cities")
.aggregate({
accumulators: [
sum("population").as("total_population")
],
groups: [equal(field("state"), null).as("state_is_null")]
})
.execute();
將傳回:
{state_is_null: true, total_population: 12130000}
{state_is_null: false, total_population: 13370000}
集結網站行為
如要瞭解各支援函式 (例如 count、sum、avg) 的匯總行為,請參閱「匯總函式」專頁。
主要群組行為
分組文件時,Firestore 會使用等號語意判斷值是否屬於同一群組。
也就是說,無論原始型別 (32 位元整數、64 位元整數、浮點數、decimal128 等),數學上相等的數值都會歸為同一組。
舉例來說,在集合 numerics 中,如果不同文件分別包含 32 位元整數 1、64 位元整數 1L 和浮點數 1.0 的 foo 值,這些值都會累計到同一個群組。執行依 foo 分組的計數會傳回:
{foo: 1.0, count: 3}
如果資料集中存在不同的等效值,群組的輸出值可以是任何一個等效值。在本範例中,foo 可以是 1、1L 或 1.0。
即使看起來是決定性行為,您也不應嘗試依賴選取特定值的行為。
記憶體用量
匯總的執行方式取決於可用的索引。如果查詢最佳化工具未選擇適當的索引,匯總作業就必須將所有群組緩衝處理到記憶體中。
如果群組數量非常龐大,或每個群組都非常大 (例如依據巨大值分組),這個階段可能會耗盡記憶體。
在這種情況下,您應套用篩選器,限制要匯總的資料集、依較少/較小的欄位分組,或按照建議建立索引,避免大量使用記憶體。查詢說明功能會提供實際查詢執行方案和剖析資料,協助您進行偵錯。