ข้อมูลรวม

คำอธิบาย

ขั้นตอนaggregateจะคำนวณผลลัพธ์ที่รวบรวมไว้ (เช่น จำนวน ผลรวม) จากเอกสารที่ขั้นตอนก่อนหน้าแสดงผล

ไม่บังคับ เมื่อระบุนิพจน์การจัดกลุ่ม ระบบจะจัดกลุ่มเอกสารตาม นิพจน์ที่ระบุ แล้วใช้ฟังก์ชันตัวสะสมกับแต่ละกลุ่ม

ไวยากรณ์

สำหรับการรวมโดยไม่มี GROUP BY aggregate stage จะใช้ นิพจน์ตัวรวบรวมที่มีนามแฝงอย่างน้อย 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ยังรองรับ การจัดกลุ่มตามผลลัพธ์ของนิพจน์ที่ซับซ้อนด้วย คุณสามารถใช้นิพจน์ใดก็ได้ที่ถูกต้องใน select สเตจเป็นคีย์การจัดกลุ่ม ซึ่งช่วยให้จัดกลุ่มได้อย่างยืดหยุ่นตามค่าหรือเงื่อนไขที่คำนวณแล้ว

ตัวอย่างเช่น หากต้องการจัดกลุ่มตามว่าฟิลด์รัฐเป็น 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 บิต จำนวนจุดลอยตัว, decimal128 ฯลฯ) จะจัดกลุ่มไว้ด้วยกันทั้งหมด

ตัวอย่างเช่น ในคอลเล็กชัน numerics ที่มีเอกสารต่างๆ ซึ่งมีfoo ค่าของจำนวนเต็ม 32 บิต 1 จำนวนเต็ม 64 บิต 1L และจำนวนทศนิยม 1.0 ตามลำดับ ระบบจะสะสมค่าทั้งหมดไว้ในกลุ่มเดียวกัน การเรียกใช้การนับ การจัดกลุ่มตาม foo จะแสดงผลดังนี้

{foo: 1.0, count: 3}

ในกรณีที่มีค่าเทียบเท่าที่แตกต่างกันอยู่ในชุดข้อมูล ค่าเอาต์พุตของกลุ่มอาจเป็นค่าเทียบเท่าใดก็ได้ ในตัวอย่างนี้ foo อาจเป็น 1, 1L หรือ 1.0

แม้ว่าดูเหมือนว่าจะเป็นการกำหนดค่า แต่คุณก็ไม่ควรพยายามอิงตาม ลักษณะการทำงานของการเลือกค่าใดค่าหนึ่ง

การใช้งานหน่วยความจำ

วิธีการดำเนินการรวมจะขึ้นอยู่กับดัชนีที่มี เมื่อเครื่องมือเพิ่มประสิทธิภาพการค้นหาไม่ได้เลือกดัชนีที่เหมาะสม การรวมต้องบัฟเฟอร์กลุ่มทั้งหมดในหน่วยความจำ

ในกรณีที่มีกลุ่มจำนวนมาก หรือแต่ละกลุ่มมีขนาดใหญ่มาก (เช่น การจัดกลุ่มตามค่าขนาดใหญ่ ) ขั้นตอนนี้อาจหน่วยความจำหมด

ในกรณีดังกล่าว คุณควรใช้ตัวกรองเพื่อจำกัดชุดข้อมูลที่จะรวม จัดกลุ่มในฟิลด์ที่เล็กลง/มีจำนวนน้อยลง หรือสร้างดัชนีตามที่แนะนําเพื่อหลีกเลี่ยง การใช้หน่วยความจําจํานวนมาก คำอธิบายการค้นหาจะให้ข้อมูลเกี่ยวกับแผนการดำเนินการค้นหาจริงและข้อมูลการจัดทำโปรไฟล์เพื่อช่วยในการแก้ไขข้อบกพร่อง