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

تتطلّب النماذج العلائقية التقليدية عمليات JOIN معقّدة ومتعدّدة الخطوات لتتبُّع السلع خلال مراحل متعددة (المورّد -> مركز التوزيع -> المطبخ المركزي -> المتجر -> المنتج النهائي). باستخدام BigQuery Graph، نصمّم هذه الروابط مباشرةً، ما يتيح إجراء طلبات بحث سهلة وسريعة باستخدام معيار ISO GQL (لغة طلبات الرسم البياني).
أهداف الدورة التعليمية
- كيفية تحديد نموذج رسم بياني استنادًا إلى جداول BigQuery الحالية
- كيفية إنشاء Property Graph داخل BigQuery
- كيفية تنفيذ طلبات بحث بالتنقّل لتتبُّع التأثيرات في المصدر والوجهة
المتطلبات
- مشروع Google Cloud تم تفعيل الفوترة فيه
- Google Cloud Shell
تقدير التكلفة
من المتوقّع أن تتكلّف هذه التجربة أقل من 5 دولار أمريكي في رسوم تحليل BigQuery، وهو مبلغ يقع ضمن مخصّصات "الطبقة المجانية" للمستخدمين الجدد.
2. الإعداد والمتطلبات
فتح Cloud Shell
ستنفّذ معظم المهام في Cloud Shell، وهي بيئة محمَّلة تتضمّن كل ما تحتاج إليه لاستخدام Google Cloud.
- انتقِل إلى Google Cloud Console.
- انقر على رمز تفعيل Cloud Shell في شريط الأدوات أعلى يسار الصفحة.
- انقر على متابعة إذا طُلب منك ذلك.
إعداد متغيرات البيئة
في Cloud Shell، اضبط رقم تعريف مشروعك لتسهيل تنفيذ الأوامر المستقبلية.
export PROJECT_ID=$(gcloud config get-value project)
تفعيل BigQuery API
تأكَّد من تفعيل BigQuery API. عادةً ما تكون هذه الميزة مفعَّلة تلقائيًا، ولكن من الأفضل التأكّد من ذلك.
gcloud services enable bigquery.googleapis.com
3- إنشاء المخطط والجداول
ستنشئ مجموعة بيانات وجداول تمثّل عناصر سلسلة الإمداد:
-
item: تعريف السلعة العام (مثل الطماطم أو الدجاج) location: المرافق (المورّدون ومراكز التوزيع والمقاهي)-
itemlocation: جدول التقاطع الذي يمثّل مواقع المستودع -
bom: قائمة المواد (تحدّد علاقات الوزن، مثلاً، يتم إدراج السلعة "أ" في السلعة "ب"). makes: يتم ربطitemlocationبـitem.stored_at: خرائط Googleitemlocationإلىlocation
إنشاء مجموعة بيانات
يمكنك تنفيذ أوامر SQL في هذا الدرس التطبيقي باستخدام Cloud Shell أو وحدة تحكّم BigQuery.
لاستخدام وحدة تحكّم BigQuery، اتّبِع الخطوات التالية:
- افتح وحدة تحكّم BigQuery في علامة تبويب جديدة.
- الصِق كل مقتطف SQL من هذا التمرين العملي في المحرّر، ثم انقر على الزر تشغيل لتنفيذه.

نفِّذ الأمر التالي في Cloud Shell أو استخدِم وحدة تحكّم BigQuery لإنشاء المخطط. ستستخدم متغيّرات العُقد في SQL.

ملاحظة: (1) لتنفيذ ذلك في Google Colab، يمكنك أيضًا استخدام أوامر BigQuery السحرية: %%bigquery تنشئ المقتطف التالي مخطط المطعم ضمن مشروعك لتخزين بيانات الرسم البياني. (2) عليك استخدام %%bigquery –project <PROJECT_ID> إذا كنت تنفّذ العملية من Google Colab. تأكَّد من ربط الحقل PROJECT_ID بالمشروع المناسب الذي تريد استخدامه: PROJECT_ID = "argolis-project-340214" # @param {"type":"string"} (3) إذا كنت تستخدم Colab، ستحتاج إلى تثبيت بعض المكتبات حسب متطلباتك. إذا كنت ستستخدم أداة عرض الرسوم البيانية، تأكَّد من تثبيت المكتبة باستخدام pip: spanner-graph-notebook==1.1.5

%%bigquery --project=$PROJECT_ID
CREATE SCHEMA IF NOT EXISTS restaurant ;
إنشاء جداول
نفِّذ رمز SQL التالي لإنشاء الجداول.
%%bigquery --project=$PROJECT_ID
-- 1. Item Table
DROP TABLE IF EXISTS `restaurant.item`;
CREATE TABLE `restaurant.item` (
itemKey STRING,
itemName STRING,
itemCategory STRING,
shelfLifeDays INT64,
PRIMARY KEY (itemKey) NOT ENFORCED
);
-- 2. Location Table
DROP TABLE IF EXISTS `restaurant.location`;
CREATE TABLE `restaurant.location` (
locationKey STRING,
locationType STRING,
locationCity STRING,
locationState STRING,
dunsNumber INT64,
PRIMARY KEY (locationKey) NOT ENFORCED
);
-- 3. ItemLocation Table
DROP TABLE IF EXISTS `restaurant.itemlocation`;
CREATE TABLE `restaurant.itemlocation` (
itemLocationKey STRING,
itemKey STRING,
locationKey STRING,
variants INT64,
PRIMARY KEY (itemLocationKey) NOT ENFORCED,
-- Foreign Key Definitions
FOREIGN KEY (itemKey) REFERENCES `restaurant.item`(itemKey) NOT ENFORCED,
FOREIGN KEY (locationKey) REFERENCES `restaurant.location`(locationKey) NOT ENFORCED
);
-- 4. BOM Table
DROP TABLE IF EXISTS `restaurant.bom`;
CREATE TABLE `restaurant.bom` (
bomKey INT64,
parentItemLocation STRING,
childItemLocation STRING,
childQuantity FLOAT64,
PRIMARY KEY (bomKey) NOT ENFORCED
);
-- 5. Makes Table
DROP TABLE IF EXISTS `restaurant.makes`;
CREATE TABLE `restaurant.makes` (
itemLocationKey STRING,
itemKey STRING,
locationKey STRING,
variants INT64,
PRIMARY KEY (itemLocationKey) NOT ENFORCED
);
DROP TABLE IF EXISTS `restaurant.stored_at`;
CREATE TABLE `restaurant.stored_at` (
itemLocationKey STRING,
itemKey STRING,
locationKey STRING,
variants INT64,
PRIMARY KEY (itemLocationKey) NOT ENFORCED
);
4. جارٍ تحميل البيانات النموذجية
لجعل هذا التمرين المعملي مكتفيًا ذاتيًا بالكامل، ستملأ الجداول ببيانات نموذجية باستخدام عبارات SQL LOAD DATA. يمثّل ذلك شبكة تبدأ بمورّد، وتمرّ عبر مركز توزيع ومطبخ مركزي، وتنتهي بمقهى للبيع بالتجزئة.
نفِّذ طلبات بحث SQL التالية لتحميل البيانات:

ملاحظة: يمكنك حذف %%bigquery إذا كنت تنفّذ مباشرةً في BigQuery Studio
%%bigquery --project=$PROJECT_ID
-- Load Item
LOAD DATA OVERWRITE `restaurant.item`
FROM FILES (format = 'CSV', uris = ['gs://supply_chain_demo/item2.csv'], skip_leading_rows = 1);
-- Load Location
LOAD DATA OVERWRITE `restaurant.location`
FROM FILES (format = 'CSV', uris = ['gs://supply_chain_demo/location.csv'], skip_leading_rows = 1);
-- Load ItemLocation
LOAD DATA OVERWRITE `restaurant.itemlocation`
FROM FILES (format = 'CSV', uris = ['gs://supply_chain_demo/itemlocation.csv'], skip_leading_rows = 1);
-- Load BOM
LOAD DATA OVERWRITE `restaurant.bom`
FROM FILES (format = 'CSV', uris = ['gs://supply_chain_demo/bom2.csv'], skip_leading_rows = 1);
-- Load Makes
LOAD DATA OVERWRITE `restaurant.makes`
FROM FILES (format = 'CSV', uris = ['gs://supply_chain_demo/makes.csv'], skip_leading_rows = 1);
-- Load StoredAt
LOAD DATA OVERWRITE `restaurant.stored_at`
FROM FILES (format = 'CSV', uris = ['gs://supply_chain_demo/itemlocation.csv'], skip_leading_rows = 1);
5- إضافة قيود وتحديد الرسم البياني
قبل إنشاء الرسم البياني، عليك تحديد العلاقات الدلالية باستخدام قيود المفتاح الأساسي والمفتاح الخارجي في SQL العادي. تساعد هذه الحقول BigQuery في فهم معرّفات العُقد وربط جداول Edge بجداول Node.
إنشاء رسم بياني للعلاقات
يمكنك الآن دمج هذه الجداول في بنية رسم بياني متماسكة واحدة تُعرف باسم restaurant.bombod.
يمكنك تحديد ما يلي:
- العُقد:
itemوlocationوitemlocation - الحواف:
makesوstored_atوconsists_of(قائمة المواد)
%%bigquery --project=$PROJECT_ID
CREATE OR REPLACE PROPERTY GRAPH `restaurant.bombod`
NODE TABLES (
`restaurant.item` KEY (itemKey) LABEL item PROPERTIES ALL COLUMNS,
`restaurant.location` KEY (locationKey) LABEL location PROPERTIES ALL COLUMNS,
`restaurant.itemlocation` KEY (itemLocationKey) LABEL itemlocation PROPERTIES ALL COLUMNS
)
EDGE TABLES (
`restaurant.makes`
KEY (itemLocationKey)
SOURCE KEY (itemLocationKey) REFERENCES `restaurant.itemlocation`(itemLocationKey)
DESTINATION KEY (itemKey) REFERENCES `restaurant.item`(itemKey)
LABEL makes PROPERTIES ALL COLUMNS,
`restaurant.bom`
KEY (bomKey)
SOURCE KEY (childItemLocation) REFERENCES `restaurant.itemlocation`(itemLocationKey)
DESTINATION KEY (parentItemLocation) REFERENCES `restaurant.itemlocation`(itemLocationKey)
LABEL consists_of PROPERTIES ALL COLUMNS,
`restaurant.stored_at`
KEY (itemLocationKey)
SOURCE KEY (itemLocationKey) REFERENCES `restaurant.itemlocation`(itemLocationKey)
DESTINATION KEY (locationKey) REFERENCES `restaurant.location`(locationKey)
LABEL stored_at PROPERTIES ALL COLUMNS
);
6. تصوُّر سلسلة الإمداد
يمكنك تنفيذ طلب بحث بالتسلسل الهرمي من الأعلى إلى الأسفل للاطّلاع على شبكة سلسلة الإمداد بأكملها. في دفتر ملاحظات عادي أو واجهة مستخدم تتيح ذلك (مثل %%bigquery --graph)، سيؤدي ذلك إلى عرض خريطة مرئية.
استخدِم طلبات بحث الرسومات البيانية المطلقة لإعداد العُقد والحواف.
ملاحظة: كما ذكرنا سابقًا، لتنفيذ ذلك في مفكرات Google Colab أو Colab Enterprise، يمكنك أيضًا استخدام أوامر BigQuery السحرية: %%bigquery. لعرض الرسم البياني في مفكرات Google Colab أو Colab Enterprise، أدرِج العلامة –graph على النحو التالي: %%bigquery –graph
%%bigquery --project=$PROJECT_ID --graph output
Graph restaurant.bombod
match p=(a:itemlocation)-[c:consists_of]->(b:itemlocation)
match q=(a)-[d:stored_at]->(e:location)
optional match z=(f)-[g:makes]-(b)
return to_json(p) as ppath, to_json(q) as qpath, to_json(z) as zpath
إخراج:

7. حالة الاستخدام 1: تتبُّع شكوى من مصدر
السيناريو: يشتكي أحد العملاء من جودة الدجاج في الساندويتش الذي اشتراه من المتجر في نيويورك. عليك تتبُّع المنتج النهائي للخلف لمعرفة مراحل تجميعه المباشرة.
طلب مسح
نفِّذ الطلب باستخدام تنسيق طلب Graph Traversal. يبحث هذا الإجراء عن consists_of الحواف التي تربط التجميعات في اتجاه المصب بمكونات المنبع.
%%bigquery --project=$PROJECT_ID --graph
GRAPH restaurant.bombod
MATCH p=(a:itemlocation)-[c:consists_of]->(b:itemlocation)
OPTIONAL MATCH q=(b)-[d:stored_at]-(e)
return to_json(p) as ppath, to_json(q) as qpath
بسبب اتجاه السهم في consists_of جدول Edge (Ingredient -> Finished)، يؤدي البحث المتجه للأعلى إلى عرض روابط تعزل بسرعة المواد التابعة ومواقع التخزين.
الناتج: 
8. حالة الاستخدام 2: تحليل التأثير
السيناريو: أدت عاصفة ثلجية إلى إغلاق مركز التوزيع في كولومبوس، أوهايو. عليك معرفة التحضيرات أو السلع النهائية التي تتأثر فورًا بذلك.
طلب مسح
تبدأ من location المحدّد الذي يمثّل مركز التوزيع، وتحدّد المستودع المخزّن هناك، وتطّلع على المنتجات النهائية التي تتطلّبها.
# @title Impact of a storm on a DC
%%bigquery --project=$PROJECT_ID --graph
Graph restaurant.bombod
match path1=(z:itemlocation)-[m:stored_at]->(dc:location) where dc.locationKey like '%DC-Sysco-Columbus-OH%'
match path2=(z:itemlocation)-[c:consists_of]->(b:itemlocation)
match path3=(b:itemlocation)-[n:makes]->(item:item)
optional match path4=(b)-[p:stored_at]->(q:location)
return to_json(path1) as path1, to_json(path2) as path2,to_json(path3) as path3, to_json(path4) as path4
الناتج: 
9- حالة الاستخدام 3: الاستدعاء اللاحق
السيناريو: يبلغك أحد المورّدين عن دفعة معيّنة من المنتجات الملوّثة: طماطم ناضجة من المورّد. عليك العثور على جميع عناصر القائمة النهائية المتأثرة في المقاهي.
طلب مسح
تبحث عن موقع المواد الخام الملوّثة، ثم تنفّذ عملية اجتياز مسار متّجهة للأسفل للعثور على العناصر المتأثرة في النهاية.
%%bigquery --project=$PROJECT_ID --graph
Graph restaurant.bombod
match path1=(a:itemlocation)-[c:consists_of]->(b:itemlocation)-[e:makes]->(f:item) where f.itemKey like '%Tomato%'
return to_json(path1) as result
يحدد طلب البحث هذا جميع العناصر التي تتطابق مع النمط "طماطم" والمرتبطة بالعلاقة المتسلسلة، ما يجعلها عملية ربط فعّالة تنتشر لاكتشاف عناصر المقهى التي يجب استرجاعها.
الناتج: 
10. تنظيف
احذف الموارد بعد إكمال خطوات التجربة الإرشادية لتجنُّب أي رسوم متبقية في مساحة عملك.
DROP SCHEMA `restaurant` CASCADE;
11. الخاتمة
تهانينا! لقد صمّمت سلسلة إمداد ونفّذت تحليل تأثير باستخدام BigQuery Graph.
الخاتمة
لقد تعلّمت كيفية:
- تحديد العلاقات الارتباطية التي تركز على الرسم البياني باستخدام المفاتيح الأساسية/الخارجية
- أنشئ مخططًا موحّدًا للكيانات.
- التنقّل بين العلاقات المتعددة العُقد بكفاءة باستخدام منطق اجتياز "طلب البحث في الرسم البياني"
للحصول على مزيد من الإحصاءات حول بنية الرسم البياني، يُرجى الانتقال إلى مستندات Google Cloud.