คำอธิบาย
สเตจ aggregate(...) จะคำนวณผลลัพธ์ที่รวม (เช่น การนับ ผลรวม) จากเอกสารที่สเตจก่อนหน้าแสดงผล
เมื่อระบุนิพจน์การจัดกลุ่ม ระบบจะจัดกลุ่มเอกสารตามนิพจน์ที่ระบุ จากนั้นใช้ฟังก์ชันสะสมกับแต่ละกลุ่ม (ไม่บังคับ)
ตัวอย่าง
สำหรับการรวมโดยไม่มีการจัดกลุ่มตาม สเตจ aggregate(...) จะใช้นิพจน์การรวมที่มีชื่อแทนอย่างน้อย 1 รายการ
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(...) ยังรองรับการจัดกลุ่มตามผลลัพธ์ของนิพจน์ที่ซับซ้อนด้วย คุณสามารถใช้นิพจน์ที่ถูกต้องใน
a select(...) สเตจเป็นคีย์การจัดกลุ่มได้
ซึ่งจะช่วยให้จัดกลุ่มได้อย่างยืดหยุ่นตามค่าหรือเงื่อนไขที่คำนวณได้
ตัวอย่างเช่น หากต้องการจัดกลุ่มตามว่าฟิลด์ state เป็นค่า Null หรือไม่ และค้นหาจำนวนประชากรทั้งหมดในแต่ละกลุ่ม ให้ทำดังนี้
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 บิต จำนวนจุดลอยตัว ทศนิยม 128 บิต ฯลฯ) จะถูกจัดกลุ่มไว้ด้วยกัน
ตัวอย่างเช่น ในคอลเล็กชัน numerics ที่มีเอกสารต่างๆ ซึ่งมีfoo
ค่าเป็นจำนวนเต็ม 32 บิต 1 จำนวนเต็ม 64 บิต 1L และจำนวนจุดลอยตัว 1.0
ตามลำดับ ค่าทั้งหมดจะถูกสะสมไว้ในกลุ่มเดียวกัน การจัดกลุ่มการนับตาม foo จะแสดงผลลัพธ์ต่อไปนี้
{foo: 1.0, count: 3}
ในกรณีที่มีค่าที่เทียบเท่ากันหลายค่าอยู่ในชุดข้อมูล ค่าเอาต์พุตของกลุ่มอาจเป็นค่าที่เทียบเท่ากันค่าใดค่าหนึ่ง
ในตัวอย่างนี้ foo อาจเป็น 1, 1L หรือ 1.0
แม้ว่าค่าที่เลือกจะดูเหมือนเป็นค่าที่กำหนดไว้ล่วงหน้า แต่คุณก็ไม่ ควรพึ่งพาลักษณะการทำงานของการเลือกค่าใดค่าหนึ่งโดยเฉพาะ
การใช้งานหน่วยความจำ
วิธีดำเนินการรวมจะขึ้นอยู่กับดัชนีที่มี เมื่อไม่มีดัชนีที่เหมาะสมซึ่งเครื่องมือเพิ่มประสิทธิภาพการค้นหาเลือกไว้ การรวมจะต้องบัฟเฟอร์กลุ่มทั้งหมดไว้ในหน่วยความจำ
ในกรณีที่มีกลุ่มจำนวนมากหรือแต่ละกลุ่มมีขนาดใหญ่มาก (เช่น การจัดกลุ่มตามค่าขนาดใหญ่) สเตจนี้อาจมีหน่วยความจำไม่เพียงพอ
ในกรณีดังกล่าว คุณควรใช้ตัวกรองเพื่อจำกัดชุดข้อมูลที่จะรวม จัดกลุ่มตามฟิลด์ที่เล็กลง/จำนวนฟิลด์ที่น้อยลง หรือสร้างดัชนีตามที่แนะนำเพื่อหลีกเลี่ยงการใช้งานหน่วยความจำจำนวนมาก Query Explain จะให้ข้อมูลเกี่ยวกับแผนการดำเนินการค้นหาจริงและข้อมูลการสร้างโปรไฟล์เพื่อช่วยในการแก้ไขข้อบกพร่อง