التجميع والدوال التجميعية
يوفر Archie Core إمكانيات قوية للتجميع والدوال التجميعية من خلال واجهة GraphQL API. يمكنك تجميع السجلات حسب قيم الحقول، وحساب دوال التجميع (COUNT، SUM، AVG، MIN، MAX، COUNT_DISTINCT)، وتصفية المجموعات بشروط HAVING، وترتيب النتائج حسب القيم المجمعة.
وسائط الاستعلام
Section titled “وسائط الاستعلام”عند استخدام التجميع والدوال التجميعية، تتوفر الوسائط التالية في أي استعلام قائمة:
| الوسيط | النوع | الوصف |
|---|---|---|
groupBy | [{TableName}GroupBy] | الحقول التي يتم تجميع النتائج وفقاً لها |
aggregateBy | [{TableName}AggregateInput] | دوال التجميع المراد حسابها |
having | [{TableName}HavingFilterInput] | تصفية المجموعات حسب نتائج التجميع |
aggregateSort | [{TableName}AggregateSortInput] | ترتيب النتائج حسب القيم المجمعة |
يمكن دمج هذه الوسائط مع وسائط قياسية مثل filter وfirst وskip وorderBy.
GroupBy
Section titled “GroupBy”يقبل وسيط groupBy مصفوفة من قيم التعداد (enum) تمثل الحقول التي يتم التجميع وفقاً لها. تتبع قيم التعداد النمط: اسم الحقل بصيغة camelCase محولاً إلى أحرف كبيرة.
اتفاقية التسمية:
| اسم العمود (DB) | اسم الحقل (GraphQL) | قيمة enum لـ GroupBy |
|---|---|---|
payment_method | paymentMethod | PAYMENTMETHOD |
created_at | createdAt | CREATEDAT |
status | status | STATUS |
category_id | categoryId | CATEGORYID |
مثال: تجميع الطلاب حسب الحالة النشطة
Section titled “مثال: تجميع الطلاب حسب الحالة النشطة”الطلب
query { students(groupBy: [ISACTIVE]) { items { isActive } count }}الاستجابة
{ "data": { "students": { "items": [ { "isActive": true }, { "isActive": false } ], "count": 2 } }}AggregateBy
Section titled “AggregateBy”يتيح وسيط aggregateBy حساب دوال التجميع على البيانات المجمعة (أو غير المجمعة). يتطلب كل تجميع function وfield اختياري وalias إلزامي.
هيكل AggregateInput
Section titled “هيكل AggregateInput”input {TableName}AggregateInput { function: AggregateFunction! field: {TableName}AggregateField alias: String!}دوال التجميع المتاحة
Section titled “دوال التجميع المتاحة”| الدالة | الوصف | هل field مطلوب؟ |
|---|---|---|
COUNT | عد الصفوف | لا (يستخدم COUNT(*) عند الحذف) |
SUM | جمع القيم الرقمية | نعم |
AVG | حساب المتوسط | نعم |
MIN | إيجاد القيمة الدنيا | نعم |
MAX | إيجاد القيمة العليا | نعم |
COUNT_DISTINCT | عد القيم المميزة | نعم |
يتبع تعداد field نفس اتفاقية الأحرف الكبيرة مثل GroupBy.
alias هو سلسلة تختارها لتسمية النتيجة. تظهر كمفتاح في كائن الاستجابة aggregates.
مثال: عد ومتوسط عمر الطلاب المجمعين حسب الحالة النشطة
Section titled “مثال: عد ومتوسط عمر الطلاب المجمعين حسب الحالة النشطة”الطلب
query { students( groupBy: [ISACTIVE] aggregateBy: [ { function: COUNT, alias: "totalStudents" } { function: AVG, field: AGE, alias: "avgAge" } ] ) { items { isActive } count aggregates }}الاستجابة
{ "data": { "students": { "items": [ { "isActive": true }, { "isActive": false } ], "count": 2, "aggregates": [ { "totalStudents": 5, "avgAge": 23.4 }, { "totalStudents": 2, "avgAge": 21.0 } ] } }}كل إدخال في مصفوفة aggregates يقابل المجموعة في نفس الفهرس في items.
Having
Section titled “Having”يصفّي وسيط having المجموعات حسب نتائج التجميع، بما يعادل جملة SQL HAVING. يستخدم نوع إدخال مخصص بثلاثة حقول.
هيكل HavingFilterInput
Section titled “هيكل HavingFilterInput”input {TableName}HavingFilterInput { alias: String! operator: HavingOperator! value: Float!}alias: يجب أن يطابق الاسم المستعار المعرّف فيaggregateBy.operator: عامل المقارنة (انظر الجدول أدناه).value: العتبة الرقمية للمقارنة ضدها.
العوامل المتاحة
Section titled “العوامل المتاحة”| العامل | المعادل في SQL |
|---|---|
EQUALS | = |
NOT_EQUALS | != |
GREATER_THAN | > |
GREATER_THAN_OR_EQUAL | >= |
LESS_THAN | < |
LESS_THAN_OR_EQUAL | <= |
مثال: المدن التي تضم أكثر من 3 طلاب
Section titled “مثال: المدن التي تضم أكثر من 3 طلاب”الطلب
query { students( groupBy: [CITYID] aggregateBy: [ { function: COUNT, alias: "studentCount" } ] having: [ { alias: "studentCount", operator: GREATER_THAN, value: 3 } ] ) { items { cityId } count aggregates }}الاستجابة
{ "data": { "students": { "items": [ { "cityId": "e14638cb-6d72-4a36-b30f-9b763136a7bb" } ], "count": 1, "aggregates": [ { "studentCount": 5 } ] } }}تُعاد فقط المجموعات التي تحقق شرط التجميع.
AggregateSort
Section titled “AggregateSort”يرتب وسيط aggregateSort النتائج المجمعة حسب قيمة مجمعة، بدلاً من حقل عادي.
هيكل AggregateSortInput
Section titled “هيكل AggregateSortInput”input {TableName}AggregateSortInput { alias: String! direction: SortDirection!}alias: يجب أن يطابق الاسم المستعار المعرّف فيaggregateBy.direction:ASC(تصاعدي) أوDESC(تنازلي).
مثال: أفضل 3 مدن حسب عدد الطلاب
Section titled “مثال: أفضل 3 مدن حسب عدد الطلاب”الطلب
query { students( groupBy: [CITYID] aggregateBy: [ { function: COUNT, alias: "studentCount" } ] aggregateSort: [ { alias: "studentCount", direction: DESC } ] first: 3 ) { items { cityId } count aggregates }}الاستجابة
{ "data": { "students": { "items": [ { "cityId": "e14638cb-6d72-4a36-b30f-9b763136a7bb" }, { "cityId": "0174dc55-d494-4ebc-a0e9-13575461cad4" }, { "cityId": "a2b3c4d5-e6f7-8901-2345-678901234567" } ], "count": 3, "aggregates": [ { "studentCount": 5 }, { "studentCount": 3 }, { "studentCount": 2 } ] } }}دمج جميع الوظائف
Section titled “دمج جميع الوظائف”يمكنك دمج filter وgroupBy وaggregateBy وhaving وaggregateSort وfirst في استعلام واحد للتحليلات المعقدة.
مثال: أفضل 5 مدن للطلاب النشطين بمتوسط عمر فوق 20، مرتبة حسب متوسط العمر
Section titled “مثال: أفضل 5 مدن للطلاب النشطين بمتوسط عمر فوق 20، مرتبة حسب متوسط العمر”الطلب
query { students( filter: { isActive: { equals: true } } groupBy: [CITYID] aggregateBy: [ { function: COUNT, alias: "studentCount" } { function: AVG, field: AGE, alias: "avgAge" } { function: MAX, field: AGE, alias: "maxAge" } ] having: [ { alias: "avgAge", operator: GREATER_THAN, value: 20 } ] aggregateSort: [ { alias: "avgAge", direction: DESC } ] first: 5 ) { items { cityId } count aggregates }}الاستجابة
{ "data": { "students": { "items": [ { "cityId": "e14638cb-6d72-4a36-b30f-9b763136a7bb" }, { "cityId": "0174dc55-d494-4ebc-a0e9-13575461cad4" } ], "count": 2, "aggregates": [ { "studentCount": 3, "avgAge": 24.3, "maxAge": 28 }, { "studentCount": 2, "avgAge": 22.5, "maxAge": 25 } ] } }}هذا الاستعلام:
- يصفّي الطلاب النشطين فقط (
filter). - يجمع حسب المدينة (
groupBy). - يحسب العدد ومتوسط العمر والحد الأقصى للعمر في كل مجموعة (
aggregateBy). - يحتفظ فقط بالمجموعات التي متوسط عمرها فوق 20 (
having). - يرتب حسب متوسط العمر تنازلياً (
aggregateSort). - يحدّ بأفضل 5 مجموعات (
first).
هيكل الاستجابة
Section titled “هيكل الاستجابة”عند استخدام التجميع، تتبع الاستجابة نوع Connection القياسي مع حقل إضافي aggregates:
| الحقل | النوع | الوصف |
|---|---|---|
items | [{TableName}!]! | السجلات المجمعة (واحد لكل مجموعة، مع قيم الحقول المجمعة) |
count | Int! | عدد المجموعات المُعادة |
pageInfo | PageInfo! | معلومات التقسيم (hasNextPage، hasPreviousPage) |
aggregates | JSON | مصفوفة من الكائنات، كل واحد يحتوي على القيم المجمعة المحسوبة مفهرسة بالاسم المستعار |
مصفوفة aggregates موازية لـ items — التجميع في الفهرس i يقابل المجموعة في الفهرس i في items.
ملاحظات مهمة
Section titled “ملاحظات مهمة”- قيم enum لـ GroupBy و AggregateField تستخدم الأحرف الكبيرة لاسم الحقل بصيغة camelCase:
payment_method→paymentMethod→PAYMENTMETHOD. - يجب أن تطابق أسماء having المستعارة اسماً مستعاراً معرّفاً في
aggregateBy. إذا لم تتطابق، يتم تجاهل شرط having. - يجب أن تطابق أسماء aggregateSort المستعارة اسماً مستعاراً معرّفاً في
aggregateBy. - COUNT بدون field يستخدم
COUNT(*)، عد جميع الصفوف في المجموعة. - يمكن دمج شروط having متعددة — يجب استيفاء الكل (منطق AND).
- تُطبّق إدخالات aggregateSort المتعددة بترتيب الأولوية (الأول هو الترتيب الرئيسي).
- وسائط التقسيم القياسية (
first،skip،after،before) تعمل مع النتائج المجمعة. - وسيط filter يُطبّق قبل التجميع (يعادل SQL WHERE)، بينما having يُطبّق بعد التجميع (يعادل SQL HAVING).