تجميع

الوصف

تحسب مرحلة aggregate(...) النتائج المجمّعة (مثل العدد والمجموع) من المستندات التي تعرضها المرحلة السابقة.

اختياريًا، عند توفير تعبير تجميع، يتم تجميع المستندات استنادًا إلى التعبيرات المقدَّمة، ثم يتم تطبيق دوال التجميع على كل مجموعة.

أمثلة

بالنسبة إلى التجميعات بدون تجميع حسب، تأخذ مرحلة 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 تتضمّن مستندات مختلفة تحتوي على foo قيم من عدد صحيح 32 بت 1 وعدد صحيح 64 بت 1L ورقم الفاصلة العائمة 1.0 على التوالي، سيتم تجميعها كلها في المجموعة نفسها. سيؤدي تشغيل عملية تجميع حسب foo إلى عرض ما يلي:

{foo: 1.0, count: 3}

في هذه الحالات التي تتضمّن قيمًا متساوية مختلفة في مجموعة البيانات، يمكن أن تكون قيمة الإخراج للمجموعة أيًا من هذه القيم المتساوية. في هذا المثال، يمكن أن تكون قيمة foo هي 1 أو 1L أو 1.0.

حتى إذا بدا السلوك محدّدًا، لا تحاول الاعتماد على سلوك اختيار قيمة معيّنة.

استخدام الذاكرة

تعتمد طريقة تنفيذ التجميع على الفهارس المتاحة. عندما لا يختار محسِّن طلب البحث فهرسًا مناسبًا، يجب أن يخزّن المجمّع مؤقتًا جميع المجموعات في الذاكرة.

في حال وجود عدد كبير جدًا من المجموعات، أو إذا كانت كل مجموعة كبيرة جدًا (مثلاً، التجميع حسب قيم كبيرة)، قد تنفد الذاكرة في هذه المرحلة.

في هذه الحالات، عليك تطبيق الفلاتر للحدّ من مجموعة البيانات التي سيتم تجميعها، أو التجميع حسب حقول أصغر أو أقل، أو إنشاء فهارس على النحو الموصى به لتجنُّب استخدام الذاكرة بشكل كبير. ستوفّر ميزة "شرح طلب البحث" معلومات عن خطة تنفيذ طلب البحث الفعلية وبيانات تحديد الملف الشخصي للمساعدة في تحديد الأخطاء وحلّها.