ข้อมูลรวม

คำอธิบาย

สเตจ 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 จะให้ข้อมูลเกี่ยวกับแผนการดำเนินการค้นหาจริงและข้อมูลการสร้างโปรไฟล์เพื่อช่วยในการแก้ไขข้อบกพร่อง