تجميع

الوصف

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

{foo: 1.0, count: 3}

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

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

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

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

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

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