كيفية استخدام المعامل “OR” في PySpark (مع أمثلة)

دليل أكاديمي شامل يشرح كيفية استخدام المعامل المنطقي “OR” في PySpark لتصفية أطر البيانات بكفاءة، مع أمثلة عملية ومقارنات دقيقة في الأداء البرمجي.

Mohammed looti أكاديمي وباحث متخصص في علم النفس
تاريخ النشر
تمت المراجعة العلمية · د. مروة عبد العظيم · 24 أكتوبر، 2026
مراجعة وتدقيق علمي معتمد تاريخ التدقيق: 24 أكتوبر، 2026
د. مروة عبد العظيم دكتوراه في علم النفس
عضو هيئة التدريس • جامعة كربلاء
معايير التدقيق والاعتماد السريري

يخضع هذا المحتوى لمعايير ضبط الجودة والتدقيق العلمي والأكاديمي الصارمة في شبكة علم النفس العربي، لضمان صحة المعلومات ودقتها السريرية ومطابقتها لأحدث الأدلة والبراهين الصادرة عن الجمعيات النفسية والطبية المعتمدة (APA / WHO).

شهدت العقود الأخيرة تحولاً جذرياً في طبيعة البيانات الرقمية من حيث الحجم والتنوع والسرعة، مما فرض تحديات بنيوية عميقة على أنظمة قواعد البيانات العلائقية التقليدية والآليات المألوفة في معالجة المعلومات. وفي ظل هذا التدفق الهائل الذي بات يُعرف اصطلاحاً باسم “البيانات الضخمة” (Big Data)، أضحى من المستحيل الاعتماد على المعالجة الأحادية أو الخوادم المركزية المستقلة لإنجاز العمليات التحليلية والاستعلامية المعقدة. برزت الحوسبة الموزعة كحل حتمي لا غنى عنه لتجاوز اختناقات الذاكرة ومحدودية وحدات المعالجة المركزية، حيث يتم تقسيم أعباء العمل وتوزيعها على مجموعات واسعة من العقد الحاسوبية المتصلة شبكياً لتعمل في تناغم وتكامل تامين لتنفيذ المهام الحسابية الفائقة.

في صلب هذا التحول المعماري، يبرز إطار عمل Apache Spark بوصفه المحرك الحسابي الأكثر نضجاً وقوة في منظومة معالجة البيانات الحديثة، ولا سيما عند اقترانه بواجهة البرمجة التطبيقية الخاصة بلغة بايثون المعروفة بـ PySpark. توفر هذه الواجهة التوليفة المثلى بين بساطة التدوين البرمجي المعهودة في بيئة بايثون والسرعة الاستثنائية لمحرك سبارك المبني أساساً بلغة سكالا والذي يعتمد على المعالجة المباشرة داخل الذاكرة (In-Memory Processing). ومع ذلك، فإن التعامل مع كتل البيانات الموزعة التي تتجاوز سعتها ملايين أو مليارات الصفوف يتطلب استيعاباً دقيقاً لآليات التصفية والفرز المنطقي، حيث لا تمثل التصفية مجرد استعلام عابر، بل هي عملية استراتيجية حاسمة تهدف إلى عزل الضجيج الإحصائي وتحسين كفاءة استخدام الموارد الحسابية وشبكات النقل الداخلية.

يركز هذا المقال الأكاديمي الموسع على دراسة وتحليل أحد أهم أركان الجبر البولياني المطبق في هندسة البيانات الموزعة، وهو المعامل المنطقي البديل “OR” (أو الفصل المنطقي) ضمن بيئة PySpark. سنستعرض بعمق نظري وتطبيقي كيفية عمل هذا المعامل بمختلف صيغه وصوره البرمجية، متتبعين المسار الذي تسلكه الشروط المنطقية من أسطر الشيفرة البرمجية وصولاً إلى محرك التحسين التحويلي “Catalyst Optimizer”. كما سنحلل الآثار المعمارية المترتبة على اختيار الصياغة البرمجية المناسبة، مع بيان الفروق الدقيقة بين التعبيرات النصية الشبيهة بلغة SQL والمعاملات الثنائية الموجهة نحو كائنات الأعمدة، مدعومين بنماذج عملية، ومقارنات أدائية، ودراسات حالة واقعية مأخوذة من بيئات الإنتاج الصناعية للبيانات الضخمة.

1. مقدمة إلى معالجة البيانات الضخمة وأهمية التصفية المنطقية في PySpark

1.1 مفهوم إطار عمل Apache Spark ودور مكتبة PySpark

يُمثل إطار عمل Apache Spark ثورة حقيقية في هندسة النظم الموزعة، حيث تم تصميمه لمعالجة أوجه القصور البنيوية التي كانت تعاني منها النماذج السابقة مثل Apache Hadoop MapReduce، ولا سيما التكاليف التشغيلية العالية الناتجة عن تكرار عمليات القراءة والكتابة على الأقراص الصلبة. تعتمد معمارية Spark على بنية تحتية مرنة ترتكز على الذاكرة العشوائية السريعة، مما يتيح تسريع معالجة البيانات بمقدار يصل إلى مئة ضعف مقارنة بالأنظمة التقليدية في بعض التطبيقات التكرارية. تشتمل المعمارية على عقدة رئيسية مسؤولة عن إدارة المهام وتوزيعها تُعرف بـ (Driver)، وعقد تابعة تقوم بالتنفيذ الفعلي للعمليات الحسابية تُدعى (Executors)، مما يسمح بتقسيم البيانات إلى أجزاء مجزأة موزعة (Partitions) تُعالج بالتوازي وبأقصى درجات الفاعلية الحسابية عبر العقد الشبكية.

تأتي مكتبة PySpark لتجسد جسراً تكاملياً استثنائياً بين مجتمع مطوري وعلماء البيانات الذين يفضلون مرونة لغة بايثون وبيئتها الغنية بالمكتبات التحليلية، وبين النواة التنفيذية عالية الأداء لمحرك Spark المبرمجة بلغة Scala والتي تعمل فوق الآلة الافتراضية لجافا (JVM). يتم تحقيق هذا الاتصال المعقد عبر مكتبة Py4J المتخصصة، والتي تسمح لكود بايثون بالتفاعل الديناميكي مع كائنات جافا داخل الذاكرة. ولقد وفرت PySpark تجريداً بيانياً رفيع المستوى يتمثل في أطر البيانات (DataFrames)، وهي هياكل جداول موزعة تحتوي على أعمدة ذات أنواع بيانات محددة ومخطط هيكلي واضح، مما ينقل تجربة البرمجة من الحوسبة منخفضة المستوى المعتمدة على مجموعات البيانات الموزعة المرنة (RDDs) إلى حوسبة معيارية منظمة وشبه منظمة قادرة على الاستفادة الكاملة من محركات التحسين الداخلية.

إن التحول من الحوسبة المتسلسلة على الأجهزة الفردية إلى الحوسبة المتوازية داخل بيئة PySpark يفرض تغييراً جذرياً في النموذج الفكري للتعامل مع الشروط المنطقية. فبدلاً من تطبيق حلقات التكرار التقليدية التي تفحص السجلات صفاً تلو الآخر بصورة متتالية ومهدرة للوقت، تعتمد أطر بيانات Spark على مفاهيم الحوسبة الوظيفية والتقييم الكسول (Lazy Evaluation). حيث تُسجل التحويلات المنطقية—بما في ذلك شروط التصفية—في رسم بياني موجه لا دوري (DAG)، ولا يتم تنفيذها حسابياً إلا عند استدعاء إجراء نهائي (Action)، مما يفتح المجال واسعاً أمام النظام لإعادة ترتيب العمليات وتحسين استهلاك الذاكرة وتوزيع الأحمال بالتساوي عبر العقد الحسابية في العنقود الموزع.

1.2 أهمية عمليات التصفية في هندسة البيانات الكبيرة

في بيئات هندسة البيانات الضخمة التي تتعامل مع تيرابايتات أو بيتابايتات من المدخلات اليومية، تُمثل عمليات التصفية المنطقية (Filtering Operations) خط الدفاع الأول لضمان استقرار البنية التحتية واستدامتها. إن استيعاب كامل مجموعات البيانات الخام في خطوط المعالجة يؤدي إلى استنزاف سريع وغير مبرر للذاكرة العشوائية المتوفرة في العقد التنفيذية (Executors)، فضلاً عن إحداث اختناقات حادة في النطاق الترددي للشبكة (Network Bandwidth) أثناء عمليات خلط البيانات ونقلها عبر الشبكة (Shuffling). ولذلك، فإن تطبيق شروط التصفية الصارمة والدقيقة يسهم في تقليص أحجام مجموعات البيانات في المراحل المبكرة من خط الأنابيب، مما يوفر مساحات الذاكرة التخزينية ويقلل من معدلات القراءة والكتابة المؤقتة على الأقراص.

إلى جانب خفض التكاليف التشغيلية للأجهزة، تسهم التصفية الفعالة في تسريع وتيرة الاستعلامات التحليلية المعقدة وعمليات التحويل اللاحقة. فعند استبعاد السجلات غير المطابقة للمواصفات أو الشروط المطلوبة منذ لحظة قراءة البيانات، تتضاءل مساحة البحث الإحصائي وتتقلص كتل البيانات المطلوب معالجتها داخل الذاكرة. ينعكس هذا التحسين المباشر بصورة إيجابية على خوارزميات التجميع (Aggregations) وعمليات الربط بين الجداول الكبيرة (Join Operations)، إذ إن تقليل عدد الصفوف المتدفقة إلى هذه العمليات الحسابية يقلل بصورة أسية من احتمالات وقوع أخطاء نفاد الذاكرة الكارثية المعروفة بـ (OutOfMemory Errors)، والتي تعد من أبرز التحديات في بيئات الحوسبة الموزعة.

تكتسي التصفية أيضاً أهمية محورية في تأهيل مجموعات البيانات المستخدمة في تدريب خوارزميات التعلم الآلي وتطبيقات الذكاء الاصطناعي. تتطلب هذه النماذج الرياضية مستويات متقدمة من الدقة والاتساق الإحصائي، حيث إن وجود السجلات التالفة، أو الشاذة، أو غير المكتملة قد يورث نماذج التنبؤ انحيازات هيكلية تفقدها فاعليتها وقابليتها للتعميم. تتيح عمليات التصفية المبرمجة بدقة استبعاد القيم الشاذة والمتطرفة، والتعامل المنهجي مع البيانات المتناقضة، وعزل الفئات المستهدفة بالدراسة فقط، مما يرفع من جودة متجهات الخصائص (Feature Vectors) المستخلصة ويسرع من تقارب خوارزميات التدريب ويقلل من الوقت الحسابي المستغرق في مرحلة تحسين المعلمات الفائقة للنماذج.

1.3 نظرة عامة على المعاملات المنطقية ودور المعامل “OR”

ترتكز كافة عمليات استعلام البيانات الموزعة في جوهرها على مبادئ الجبر البولياني (Boolean Algebra)، وهو النظام الرياضي الرمزي الذي صاغه العالم جورج بول لدراسة المتغيرات المنطقية التي لا تحتمل سوى قيمتين أساسيتين: الصواب (True) أو الخطأ (False). وعند تطبيق هذا النظام على صفوف أطر البيانات الموزعة في PySpark، يتحول كل صف في الجدول إلى مدخل مستقل يُقيم بناءً على دالة افتراضية تُعيد ناتجاً بوليانياً يحدد ما إذا كان الصف سيبقى ضمن مجموعة البيانات الناتجة أم سيتم إقصاؤه نهائياً من خط المعالجة الحسابي.

يحتل المعامل المنطقي البديل “OR” (أو بوابة الفصل المنطقي) مكانة استثنائية ضمن عائلة المعاملات المنطقية، نظراً لطبيعته القائمة على التوسيع والشمول بدلاً من التضييق والحصر. على النقيض من معامل العطف المنطقي “AND” الذي يفرض تحقق جميع المعايير والشروط مجتمعة دون استثناء، مما يقلص من عدد السجلات المسترجعة، يعمل المعامل “OR” على فتح آفاق المطابقة المنطقية لتشمل أي سجل يتحقق فيه شرط واحد على الأقل من بين مجموعة الشروط المطروحة. يتيح هذا السلوك للمهندسين والمحللين استخراج مجموعات البيانات التي تغطي فئات متنوعة وحالات متباينة في آن واحد، مثل استهداف العملاء متعددي الانتماءات الجغرافية أو التقاط الأنماط التشغيلية المتعددة للأنظمة الرقمية.

ومع ذلك، يفرض تطبيق المعامل “OR” في بيئة PySpark تحديات برمجية ودلالية غير يسيرة، ولا سيما للمطورين الذين اعتادوا على كتابة شيفرات بايثون القياسية المصممة للحوسبة الفردية. فالطريقة التي تُقيم بها لغة بايثون التعبيرات الشرطية تختلف اختلافاً جوهرياً عن الكيفية التي يتعامل بها محرك الحوسبة الموزعة في Spark مع كائنات الأعمدة. يؤدي هذا التباين البنيوي إلى وقوع المبرمجين في أخطاء شائعة ناتجة عن الخلط بين المعاملات المنطقية للتحكم في التدفق ومعاملات العمليات الثنائية المطبقة على متجهات البيانات، مما يجعل الفهم المعمق لقواعد التقييم وديناميكيات المعاملات أمراً لا غنى عنه لأي مهندس بيانات يسعى لكتابة شيفرات تتسم بالأمان الحسابي والكفاءة الأدائية العالية.

2. المفاهيم الأساسية للمعامل “OR” في بيئة PySpark

2.1 التعريف النظري والمنطقي للبوابة المنطقية OR في سياق الجداول

تخضع البوابة المنطقية “OR” لقواعد رياضية صارمة تُحدد ناتج دمج قيمتين منطقيتين أو أكثر، وتتلخص هذه القواعد فيما يُعرف بجدول الحقيقة المنطقي (Truth Table). وفقاً للمنطق البولياني الثنائي التقليدي، فإن ناتج العملية المنطقية المرتبطة بالمعامل “OR” يكون صواباً (True) إذا كانت إحدى القيمتين المدخلتين صواباً على الأقل، بينما لا يُسفر التقييم عن الخطأ (False) إلا في حالة واحدة مطلقة، وهي عندما تكون كافة المدخلات خاطئة تماماً. يضمن هذا المنطق المتساهل أو الشامل (Inclusive OR) توسيع رقعة البحث واستعادة أكبر قدر ممكن من السجلات التي تلبي الحد الأدنى من المعايير المقبولة في الاستعلام.

غير أن التطبيق الفعلي لهذا المنطق داخل جداول وقواعد البيانات الضخمة يصطدم بوجود حالة ثالثة لا مفر منها، وهي غياب البيانات أو ما يُصطلح عليه بالقيمة الخالية (Null Value). تفرض هذه الحالة الانتقال من المنطق الثنائي الكلاسيكي إلى المنطق الثلاثي القِيَم (Three-Valued Logic) المعروف تاريخياً بمنطق كلين (Kleene Logic). في هذا السياق، تصبح المدخلات المحتملة للشرط هي: صحيح (True)، أو خاطئ (False)، أو غير محدد (Null). يتعامل المعامل “OR” مع هذه الحالة ببراعة منطقية فائقة؛ فإذا قورنت قيمة صحيحة (True) مع قيمة خالية (Null) عبر المعامل “OR”، يكون الناتج النهائي دائماً صحيحاً (True)، لأن تحقق أحد الشرطين كافٍ بذاته لترجيح كفة الصواب بغض النظر عما تخفيه القيمة المجهولة. في المقابل، إذا كانت القيمة الأولى خاطئة (False) والأخرى خالية (Null)، يصبح الناتج غير محدد (Null)، مما يؤدي في نهاية المطاف إلى استبعاد الصف لأن التصفية لا تقبل سوى النتائج المؤكدة بالصواب الصريح.

إن فهم هذا السلوك المنطقي المتشعب في سياق الجداول الموزعة أمر في غاية الأهمية لتجنب فقدان البيانات غير المقصود. فعند تطبيق المعامل “OR” على أعمدة تحتوي على قيم خالية، يجب على المهندس أن يدرك بدقة كيف ستتفاعل هذه القيم مع الشروط الأخرى، وكيف سيؤثر المنطق الشامل على حجم النتائج النهائية، مما يحول دون ظهور سلوكيات غير متوقعة تؤثر سلباً على سلامة التحليلات الإحصائية وتطبيقات المعالجة اللاحقة.

2.2 الفرق بين المعاملات المنطقية في بايثون ومحرك Spark

يقع الكثير من مهندسي البيانات المبتدئين في فخ دلالي ناتج عن التناقض البنيوي بين بيئة لغة بايثون الأصلية ومنظومة PySpark الموزعة. في لغة بايثون القياسية، تُمثل الكلمة المفتاحية or معاملاً منطقياً يتحكم في مسار التدفق ويُقيم التعبيرات تقييماً قصير الدائرة، ويعيد أحد المعاملين بناءً على قيمته الصوابية (Truthiness). تفترض هذه الآلية أن التعبير يمكن تحويله فورياً ومباشرة إلى قيمة بوليانية فردية ومطلقة داخل ذاكرة البرنامج المحلي.

في المقابل، عندما نتعامل مع كائنات PySpark، فإن الإشارة إلى عمود ما—مثل التعبير df['age'] > 25—لا تعيد قيمة بوليانية واحدة (True أو False)، بل تعيد كائناً مجرداً من النوع Column. هذا الكائن لا يمثل قيمة حسابية منفذة، بل هو عقدة في شجرة التعبيرات الرمزية التي تشير إلى كيفية حساب تلك القيمة لكل صف من صفوف الجدول عبر مئات الخوادم الموزعة في وقت لاحق. وعند محاولة إقحام الكلمة المفتاحية المدمجة في بايثون or بين كائنين من نوع Column، تحاول بايثون داخلياً تحويل كائن العمود إلى قيمة بوليانية عبر استدعاء الدالة السحرية __bool__()، وهو ما يرفضه محرك PySpark رفضاً قاطعاً، مولداً استثناءً برمجياً شهيراً من نوع TypeError أو ValueError يوضح استحالة اختزال عمود موزع كامل في قيمة بوليانية فردية.

لحل هذه المعضلة البنيوية، تعتمد مكتبة PySpark على مفهوم التحميل الزائد للمعاملات (Operator Overloading). حيث قامت بإعادة تعريف المعامل الثنائي (Bitwise OR)، المُمثل بالرمز | (الخط الرأسي Pipe)، ليعمل كمعامل فصلي منطقي يتعامل حصرياً مع كائنات الأعمدة Column. يقوم هذا الرمز ببناء تعبير منطقي مركب يدمج بين الشروط دون محاولة تقييمها محلياً، مما يسمح بتمرير التعبير الموحد بالكامل إلى محرك Spark التنفيذي ليتولى معالجته بالتوازي فوق العقد الحسابية.

2.3 آلية تقييم الشروط داخل محرك Catalyst Optimizer

تخضع جميع التعبيرات المنطقية في PySpark لإشراف محرك تحسين الاستعلامات المتقدم المعروف باسم Catalyst Optimizer. يُعد هذا المحرك بمثابة العقل المفكر لـ Spark، إذ يقوم بتحويل الشروط المنطقية والتحويلات البرمجية التي يكتبها المطور إلى خطة تنفيذ فيزيائية شديدة الكفاءة. عند صياغة شرط تصفية يعتمد على المعامل “OR”، يقوم Catalyst بتحليل الشيفرة وتفكيكها إلى شجرة تعبيرات مجردة (Abstract Syntax Tree)، حيث تُمثل العقد أوراقاً وفروعاً منطقية تخضع لعمليات التحليل والتبسيط الرياضي القياسي المستند إلى قواعد الجبر العلائقي وقوانين دي مورغان المنطقية.

تتمثل إحدى أقوى الاستراتيجيات التي ينفذها Catalyst في آلية “دفع الشروط للأسفل” (Predicate Pushdown). في هذه العملية، يحاول المحرك دفع شروط التصفية إلى أدنى نقطة ممكنة في شجرة التنفيذ، أي إلى مستوى قراءة مصادر البيانات الأصلية كملفات Parquet أو جداول التخزين المتطورة مثل Delta Lake. إذا كان التعبير المنطقي المركب يحتوي على المعامل “OR”، يقوم المحرك بفحص ما إذا كان بإمكانه استخدام فهارس الملفات والإحصائيات الوصفية المخزنة في ترويسات الأعمدة—مثل القيم الدنيا والعليا (Min/Max Statistics)—لتخطي كتل كاملة من البيانات (Data Skipping) لا يمكن لأي من طرفي شرط “OR” أن يتحقق فيها. هذا التخطي يقلل بصورة جذرية من كميات البيانات المنقولة من وحدات التخزين إلى الذاكرة العشوائية.

علاوة على ذلك، يستفيد المحرك من التقييم قصير الدائرة (Short-circuit Evaluation) ولكن على مستوى خطة التنفيذ المترجمة عبر ميزة تجميع الأكواد بالكامل في وقت التشغيل (Whole-Stage Code Generation). حيث يقوم المحرك بتوليد كود Java Bytecode محسّن ديناميكياً يقيّم العمليات بأقصى سرعة ممكنة. في تعبيرات “OR”، إذا تحقق الشرط الأول لصف معين وأعاد نتيجة صائبة، يقوم الكود المولد بتجاوز تقييم الشرط الثاني فوراً والانتقال مباشرة إلى معالجة الصف التالي، مما يوفر ملايين الدورات الحسابية لوحدة المعالجة المركزية (CPU Cycles) عند معالجة المليارات من السجلات الرقمية.

3. إعداد بيئة العمل وإنشاء DataFrame تجريبي

3.1 تهيئة جلسة SparkSession وضبط الإعدادات

تمثل نقطة الانطلاق في أي مشروع يعتمد على PySpark تهيئة كائن جلسة العمل الموحدة المعروف بـ SparkSession. منذ إطلاق الإصدار 2.0 من Apache Spark، أصبحت هذه الجلسة هي البوابة الأساسية والرسمية للوصول إلى كافة الوظائف البرمجية، متضمنة واجهات التعامل مع أطر البيانات والعمليات المبنية على لغة SQL، مستبدلة السياقات السابقة المتعددة مثل SparkContext وSQLContext في إطار برمجي واحد متماسك وسهل الإدارة.

تتضمن تهيئة الجلسة تحديد استراتيجية توزيع المعالجة وموارد الذاكرة المخصصة. في بيئة التطوير المحلية، يمكن تحديد النطاق الرئيسي باستخدام النمط master("local[*]")، والذي يوجه محرك Spark إلى استغلال كافة الأنوية والخيوط الحسابية المتاحة في معالج الحاسوب الشخصي لمحاكاة عنقود حوسبي متكامل. كما تتيح الجلسة للمطور ضبط المعايير الأدائية الحرجة، مثل حجم الذاكرة المخصصة للسائق (Driver Memory) والمنفذين (Executor Memory)، وتكوين معلمات التخصيص الديناميكي للذاكرة المؤقتة. يضمن التحقق البرمجي من كائن الجلسة بعد إنشائه نجاح الاتصال وتأكيد توافق إصدار بيئة بايثون مع المحرك التنفيذي الأساسي لجافا.

يتم استدعاء فئة البناء (Builder Pattern) المدمجة لتهيئة الجلسة بدقة متناهية، كما يتضح من النمط المعياري التالي:

من مكتبة pyspark.sql يتم استيراد SparkSession، ثم يُستدعى البناء:
spark = SparkSession.builder.appName("PySpark_OR_Operator_InDepth").master("local[*]").config("spark.sql.shuffle.partitions", "4").getOrCreate()
يوضح السطر السابق إنشاء جلسة تحمل اسماً دلالياً، مع قصر عدد أقسام الخلط المؤقتة على أربعة أقسام لتلائم المعالجة المحلية السريعة، وتفادي استهلاك الموارد المفرط في البيئات التجريبية المحدودة.

3.2 بناء مجموعة البيانات النموذجية للمشروع

لإجراء التطبيقات العملية والمقارنات الأدائية بصورة منهجية، يتعين بناء مجموعة بيانات نموذجية متوازنة تجمع بين التنوع الهيكلي والخصائص الرقمية والفئوية، فضلاً عن احتوائها المتعمد على بعض التناقضات المنهجية التي تخدم أهداف الفحص المنطقي. سنعتمد في هذا الدليل على سيناريو رياضي يتتبع أداء فرق ولاعبين في دوري كرة سلة افتراضي، حيث يتضمن كل صف بيانات محددة عن اسم الفريق، وعدد النقاط المحرزة، والتمريرات الحاسمة المكتملة.

يتم تخزين هذه السجلات الأولية في صورة مصفوفة بايثون تحتوي على صفوف محددة، مما يتيح تمثيل حالات اختبار متباينة تلائم استكشاف سلوكيات المعامل “OR”. تشمل الحالات لاعبين حققوا نقاطاً استثنائية، وآخرين حققوا نقاطاً منخفضة ولكنهم ينتمون لفرق استراتيجية معينة، بالإضافة إلى سجلات تتضمن قيماً متطرفة أو متطابقة عمداً لاختبار التقييم الحصري والشامل. بعد تعريف مصفوفة الصفوف الأولية، يتم صياغة قائمة بأسماء الأعمدة المرتبطة بها تمهيداً لدمجهما معاً داخل الإطار البياني الموزع.

تُنفذ هذه الخطوة عبر استدعاء الدالة المباشرة createDataFrame() المرتبطة بكائن الجلسة. يتم تمرير البيانات الخام وقائمة الأعمدة إلى الدالة، ليتولى المحرك توزيع البيانات وتحويلها داخلياً إلى أقسام موزعة جاهزة للمعالجة. يمثل هذا الكائن الناتج الأساس البرمجي الذي ستُجرى عليه كافة العمليات اللاحقة لشرح المعامل “OR”، مما يتيح محاكاة دقيقة لكيفية تعامل محركات البيانات مع جداول الإنتاج الضخمة ولكن في قالب تجريبي خاضع للرقابة المعملية الدقيقة.

3.3 فحص بنية البيانات ومخططها الهيكلي (Schema)

بمجرد اكتمال بناء كائن الـ DataFrame التجريبي، يقتضي البروتوكول الهندسي الصارم فحص بنية البيانات والتأكد من ملاءمة المخطط الهيكلي (Schema) المستنتج تلقائياً بواسطة محرك Spark. لا تقتصر هذه الخطوة على التحقق البصري السطحي، بل تهدف إلى تأكيد توافق أنواع البيانات المخزنة مع العمليات الرياضية والمنطقية المقررة لاحقاً، حيث إن عدم تطابق الأنواع يعد من أبرز مسببات فشل الاستعلامات في البيئات الموزعة.

يتم استعراض الصفوف الأولى من الجدول عبر استدعاء دالة العرض show()، والتي تؤدي إلى إطلاق إجراء حسابي (Action) يقوم بجمع عدد محدود من الصفوف من العقد المنفذة وتنسيقها في جدول نصي أنيق يوضح القيم المحتواة في كل حقل. يتيح هذا الفحص التحقق من صحة ترصيف الأعمدة والبيانات، والتأكد من عدم حدوث أي إزاحة عرضية أثناء تحويل الهياكل غير المعيارية لبايثون إلى صيغة Spark الجدولية.

في أعقاب ذلك، يتم استدعاء دالة طباعة المخطط printSchema()، والتي تكشف عن الشجرة الهيكلية لأنواع البيانات المسندة لكل عمود. يظهر المخطط الهيكلي في هذا السياق تنوعاً بين الأعمدة الفئوية النصية المتمثلة في نوع StringType (مثل عمود اسم الفريق)، والأعمدة الكمية الرقمية المتمثلة في نوع IntegerType أو LongType (مثل أعمدة النقاط والتمريرات). إن إدراك نوع البيانات لكل عمود يكتسي أهمية حاسمة عند كتابة شروط التصفية، حيث تتطلب المقارنات الرقمية قيماً صريحة تتوافق مع القواعد الجبرية، بينما تتطلب السلاسل النصية تضمين محددات اقتباس دقيقة لتفادي استثناءات التحليل النحوي في محرك الاستعلامات.

4. الطريقة الأولى: استخدام المعامل “OR” عبر تعبيرات SQL النصية

4.1 البنية النحوية لتمرير الشروط كسلاسل نصية في دالة filter()

توفر مكتبة PySpark مرونة فائقة تسمح لمهندسي البيانات بكتابة شروط التصفية باستخدام تعبيرات نصية مطابقة تماماً للقواعد النحوية المتبعة في لغة الاستعلامات البنيوية القياسية (ANSI SQL). يتم تمرير هذه التعبيرات ككتلة نصية مقتبسة (String Literal) مباشرة إلى دالة التصفية الأساسية filter()، أو لاسمها المستعار المطابق وظيفياً where(). تتيح هذه الميزة للمطورين استثمار معرفتهم السابقة بلغة SQL دون الحاجة إلى استيعاب التفاصيل المعقدة لواجهات برمجة الكائنات في PySpark في المراحل الأولى من التطوير.

تعتمد هذه الصياغة على استخدام الكلمة المفتاحية or المكتوبة بحروف صغيرة أو كبيرة (حيث لا يتأثر محرك التحليل بحالة الأحرف في الكلمات المفتاحية للغة SQL). يتم وضع الشرط المنطقي الكامل داخل علامتي اقتباس مفردتين أو مزدوجتين، مع تضمين أسماء الأعمدة والقيم المستهدفة والمعاملات المقارنة في نسق تعبيري متواصل. تفرض القواعد النحوية لهذه الطريقة إحاطة القيم النصية داخل السلسلة بعلامات اقتباس إضافية متمايزة (كاستخدام علامات الاقتباس المفردة داخل نص محاط بعلامات مزدوجة)، لتمييز القيم الثابتة عن أسماء الأعمدة، كما هو متبع في كافة أنظمة قواعد البيانات العلائقية الحديثة.

من الناحية المعمارية، عندما تستقبل دالة filter() وسيطاً نصياً، فإنها تقوم بتمريره فوراً إلى المحلل اللغوي الداخلي لـ Spark SQL (المسمى Catalyst SQL Parser). يقوم هذا المحلل بتفكيك السلسلة النصية إلى رموز معجمية (Tokens)، ثم يبني منها شجرة نحوية مجردة يتم تحويلها لاحقاً إلى كائنات منطقية مطابقة لتلك التي تُبنى برمجياً عبر دوال الكائنات، مما يعني أن التعبير النصي لا يبقى نصاً أثناء التنفيذ، بل يُترجم بالكامل إلى تمثيل برمجي ثنائي عالي الكفاءة داخل الذاكرة.

4.2 تطبيق عملي: تصفية السجلات بناءً على قيم النقاط والفريق

لتطبيق هذا الأسلوب النصي عملياً، نفترض وجود جدول البيانات التجريبي الذي يتضمن معلومات أداء الفرق الرياضية، حيث نسعى لاستخراج كافة السجلات التي تحقق أحد المعيارين التاليين: إما أن يكون اللاعب قد سجل عدداً من النقاط يتجاوز 9 نقاط (معيار رقمي تفوقي)، أو أن يكون اللاعب منتمياً إلى الفريق ‘B’ (معيار فئوي جغرافي أو إداري)، بغض النظر عن عدد النقاط التي أحرزها. يجسد هذا الاستعلام جوهر المعامل “OR” الذي يوسع دائرة الاختيار لتشمل النخب الهجومية من جهة، وأعضاء الفريق المستهدف من جهة أخرى.

تتم كتابة الشيفرة البرمجية المنفذة لهذا الاستعلام بأسلوب السلاسل النصية على النحو التالي:
filtered_df = df.filter("points > 9 or team = 'B'")
ثم يُتبع ذلك باستدعاء دالة العرض لمشاهدة النتائج المصفاة:
filtered_df.show()
يُلاحظ في هذه الصياغة استخدام معامل المساواة الفردي (=) أو المزدوج (==)، حيث يقبل محلل Spark SQL كِلا الشكلين داخل التعبيرات النصية، مما يمنح المطورين أريحية تشابه بيئات SQL التقليدية.

عند تنفيذ هذه الشيفرة ومطابقة المخرجات مع الجدول الأساسي، نجد أن السجلات التي تظهر في الناتج النهائي تتضمن جميع لاعبي الفريق ‘B’ حتى أولئك الذين حققوا نقاطاً تقل عن 9، كما تتضمن لاعبي الفرق الأخرى (مثل الفريق ‘A’ أو ‘C’) شرط أن تكون نقاطهم المسجلة قد تجاوزت الرقم 9 بالفعل. يتم استبعاد السجلات فقط عندما يفشل اللاعب في تحقيق الشرطين معاً؛ أي عندما ينتمي لفريق مغاير لـ ‘B’ وتكون نقاطه في الوقت ذاته مساوية لـ 9 أو أقل منها، مما يقدم دليلاً عملياً قاطعاً على نجاح الفصل المنطقي الشامل.

4.3 مزايا ومحددات الأسلوب النصي (SQL Expressions)

يتميز أسلوب التعبيرات النصية بمجموعة من المزايا التشغيلية الجذابة، يأتي في مقدمتها وضوح القراءة وبساطة البنية النحوية. تتيح هذه التعبيرات للمهندسين والمحللين—وخاصة أولئك الذين يمتلكون خلفيات راسخة في قواعد البيانات التقليدية ومستودعات البيانات—كتابة شروط معقدة وطويلة دون الحاجة إلى استيراد دوال إضافية من مكتبة pyspark.sql.functions ودون الانشغال بتفاصيل إدارة الأقواس الثنائية الصارمة. كما تتيح هذه الطريقة سهولة نقل الاستعلامات المكتوبة مسبقاً في أنظمة مثل Oracle أو PostgreSQL أو Hive مباشرة إلى خطوط معالجة PySpark بأقل قدر ممكن من التعديلات النحوية.

على الجانب الآخر، ينطوي الاعتماد على السلاسل النصية على محددات معمارية وبرمجية بالغة الخطورة، يتمثل أبرزها في انعدام التحقق من صحة الأنواع والرموز أثناء وقت التجميع (Compile-time Type Safety). فعند كتابة اسم عمود بشكل خاطئ داخل السلسلة النصية—كأن يكتب المطور “pointss” بدلاً من “points”—فإن بيئة بايثون وأدوات التدقيق الساكن (Linters) لن تتمكن من اكتشاف هذا الخطأ مسبقاً، بل سيمر الكود بسلام حتى مرحلة التشغيل الفعلي (Runtime)، ليتوقف البرنامج فجأة مولداً استثناء تحليلياً من نوع AnalysisException يشير إلى عدم العثور على العمود في الجدول الموزع.

علاوة على ذلك، تتسم التعبيرات النصية بضعف مقاومتها لإعادة الهيكلة البرمجية (Refactoring). فإذا تغيرت أسماء الأعمدة في المراحل المتقدمة من تطوير المشروع، لن تتمكن بيئات التطوير المتكاملة (IDEs) مثل PyCharm أو VS Code من تعقب وتحديث الأسماء المكتوبة داخل السلاسل النصية تلقائياً. كما تصبح هذه الطريقة شديدة التعقيد والهشاشة عندما تتطلب متطلبات الأعمال بناء شروط تصفية ديناميكية تعتمد على متغيرات تتغير استناداً إلى مدخلات المستخدمين، حيث يضطر المطور إلى استخدام تقنيات دمج وتنسيق النصوص (String Interpolation)، مما يفتح الباب واسعاً أمام أخطاء التنسيق المعقدة ويزيد من احتمالات الثغرات المشابهة لهجمات حقن الاستعلامات (SQL Injections).

5. الطريقة الثانية: استخدام الرمز المنطقي الثنائي (|) مع دوال الأعمدة

5.1 الصياغة البرمجية باستخدام دوال وكائنات Column

تمثل الطريقة الثانية النهج البرمجي الأكثر توافقاً مع فلسفة البرمجة كائنية التوجه (OOP) والنموذج الوظيفي المتبع في مكتبة PySpark. في هذا الأسلوب، لا يتم التعامل مع الشروط كسلاسل نصية مصمتة، بل يتم تشييدها برمجياً عبر تفكيك الجداول إلى كائنات برمجية مستقلة تمثل الأعمدة (Column Objects). يتيح هذا النمط للغات البرمجة الحديثة تفعيل أدوات الفحص المبكر، ويسهل إدارة التعقيدات الاستعلامية داخل خطوط هندسة البيانات المتقدمة.

للإشارة إلى أعمدة الجدول، توفر PySpark ثلاثة أنماط برمجية شائعة:

  • نمط السمة (Attribute Style): مثل df.points، وهو أسلوب سريع ومباشر ولكنه يعجز عن التعامل مع الأعمدة التي تحتوي أسماؤها على مسافات أو رموز خاصة.
  • نمط الفهرس (Index Style): مثل df['points']، وهو نمط متين يدعم كافة أشكال أسماء الأعمدة البرمجية بأمان تام.
  • استخدام دالة col() المعيارية: المستوردة مباشرة من مكتبة pyspark.sql.functions، مثل col("points")، وهو الأسلوب الأكثر مرونة وانتشاراً في أوساط المطورين المحترفين، نظراً لعدم تقييده بالربط المباشر مع متغير الـ DataFrame المحدد مسبقاً، مما يسهل كتابة دوال تصفية قابلة لإعادة الاستخدام عبر جداول متعددة.

لتمثيل المعامل المنطقي البديل “OR” في هذه البنية الكائنية، يتم استخدام الرمز المنطقي الثنائي | (Pipe). يقوم هذا الرمز بتطبيق آلية التحميل الزائد على المعاملات لربط كائنين منفصلين من كائنات الأعمدة، لينتج عنهما كائن عمود ثالث يمثل التعبير البولياني المجمع. هذا التعبير لا يتم تقييمه فورياً، بل يُدمج ضمن المخطط المنطقي ليتم تنفيذه على التوازي فوق العقد الحسابية عند طلب استخراج البيانات.

5.2 الأهمية الجوهرية للأقواس الدائرية لتفادي أخطاء الأسبقية

تعد مسألة أسبقية العمليات (Operator Precedence) في لغة بايثون من أكثر النقاط الحيوية التي يجب على كل مطور بيانات استيعابها بدقة متناهية عند التعامل مع معاملات الأعمدة الثنائية. في التسلسل الهرمي لقواعد لغة بايثون الصارمة، تمتلك المعاملات الثنائية—بما فيها معامل الفصل الثنائي | ومعامل العطف الثنائي &—أسبقية تنفيذ أعلى بكثير من معاملات المقارنة المنطقية العلائقية مثل المساواة (==)، أو عدم المساواة (!=)، أو علامات الأكبر والأصغر من (>, <, >=, <=).

يترتب على هذا الترتيب الرياضي خطأ جسيم وشائع للغاية عند كتابة التعبيرات الشرطية دون أقواس حماية؛ فإذا قام المطور بكتابة الشيفرة بالشكل التالي:
df.points > 9 | df.team == 'B'
فإن بايثون لن تقوم بمقارنة النقاط أولاً ثم الانتقال لمقارنة الفريق كما يتبادر للذهن البشري، بل ستبادر فوراً إلى محاولة تقييم الجزء الأوسط ذي الأسبقية العليا، وهو: 9 | df.team. يؤدي هذا الدمج الشاذ بين عدد صحيح وكائن عمود نصي إلى انهيار العملية برمتها وإطلاق استثناءات فورية تفيد بعدم إمكانية تطبيق العمليات الثنائية بين أنواع بيانات غير متوافقة، أو إطلاق أخطاء نحوية مبهمة تربك المطور غير المتمرس.

لتفادي هذا السلوك غير المرغوب وضمان تسلسل حسابي صحيح، تفرض بيئة PySpark قاعدة إلزامية قاطعة: يجب تطويق كل تعبير مقارنة مستقل داخل زوج منفصل من الأقواس الدائرية () بصورة محكمة قبل ربطه بالمعامل المنطقي |. وبذلك تصبح الصياغة الصحيحة رياضياً وبرمجياً كالتالي:
(df.points > 9) | (df.team == 'B')
تجبر هذه الأقواس مفسر بايثون على إتمام عمليات المقارنة وإنتاج كائنات التعبيرات المنطقية للطرفين أولاً وبشكل منعزل، قبل أن يتدخل الرمز | لدمجهما في شجرة شرطية موحدة، مما يحقق السلامة الدلالية للاستعلام.

5.3 تطبيق عملي مفصل باستخدام الصيغة البرمجية الثنائية

لنقل هذه المفاهيم إلى التطبيق الإجرائي، نقوم بتنفيذ استعلام التصفية المشروط باستخدام الرمز الثنائي | على الـ DataFrame التجريبي الذي قمنا بإنشائه مسبقاً، محاكين السيناريو ذاته الذي اختبرناه في الطريقة النصية لضمان قياس التماثل والتحقق من سلامة الأداء عبر كلا الأسلوبين البرمجيين.

نبدأ باستيراد الدالة المعيارية col من الحزمة المخصصة لتعزيز مقروئية الكود:
from pyspark.sql.functions import col
ثم نقوم بصياغة تعبير التصفية الموجه نحو الكائنات وتمريره إلى دالة filter() مع تطبيق قواعد الأقواس الإلزامية بدقة متناهية:
filtered_df_bitwise = df.filter((col("points") > 9) | (col("team") == "B"))
ولاستعراض السجلات المسترجعة نطالب المحرك بعرض النتائج:
filtered_df_bitwise.show()

عند تتبع مسار التقييم المنطقي الذي يسلكه محرك Spark لكل صف على حدة، نجد الآلية الحسابية تسير وفق الخطوات التالية:

  • تقييم الشق الأيسر: يفحص المحرك ما إذا كانت قيمة عمود points أكبر من الرقم 9؛ إذا تحقق ذلك للصف المعني، يتولد ناتج جزئي صائب.
  • تقييم الشق الأيمن: يفحص المحرك ما إذا كانت قيمة عمود team تطابق السلسلة النصية “B”؛ إذا تحقق ذلك، يتولد ناتج جزئي صائب.
  • الدمج الثنائي: يطبق المحرك بوابة الفصل المنطقي | بين الناتجين الجزئيين، فإن كان أحدهما أو كلاهما صائباً اعتُمد الصف ضمن النتائج النهائية وتم تمريره للمرحلة التالية، وإن كان كلاهما خاطئاً تم استبعاد الصف تماماً من الذاكرة الحسابية.

تثبت المقارنة البصرية والمصفوفية للنتائج المستخرجة بهذه الطريقة تطابقها التام والمطلق مع مخرجات الأسلوب النصي (SQL Expression) السابق، مما يؤكد أن الاختلاف يكمن فقط في واجهة التدوين البرمجية وطريقة صياغة الشيفرة، بينما تظل الغايات المنطقية والنتائج الحسابية واحدة عبر مختلف بيئات التنفيذ في Apache Spark.

6. مقارنة معمارية وأدائية بين الطريقة النصية والرمز الثنائي (|)

6.1 تحليل خطط التنفيذ (Execution Plans) في Spark

لإجراء تقييم علمي دقيق للمفاضلة بين أسلوب التعبيرات النصية واستخدام الرمز الثنائي |، يتعين علينا الغوص عميقاً في كواليس محرك التنفيذ وفحص “خطط التنفيذ” (Execution Plans) التي يولدها محرك Catalyst لكلتا الحالتين. يوفر إطار عمل PySpark دالة متخصصة بالغة الأهمية هي explain(True)، والتي تتيح للمهندسين إظهار المراحل الأربع لتحليل الاستعلام: الخطة المنطقية الأولية (Parsed Logical Plan)، والخطة المحللة (Analyzed Logical Plan)، والخطة المنطقية المحسنة (Optimized Logical Plan)، والخطة الفيزيائية النهائية (Physical Plan).

عند استدعاء دالة explain() على كلا النموذجين المصفىين، تتكشف حقيقة معمارية جوهرية: على الرغم من أن الخطة المنطقية الأولية تُظهر تبايناً طفيفاً في كيفية تلقي التعبير (حيث تُظهر الطريقة النصية مرحلة تحليل معجمي إضافية في البداية عبر الـ SQL Parser بينما تتجاوز الطريقة الكائنية هذه الخطوة لتنشئ شجرة التعبيرات مباشرة)، إلا أن كلتا الطريقتين تتطابقان تماماً وبصورة مذهلة بمجرد الوصول إلى مرحلة “الخطة المنطقية المحسنة”. فالمحرك يقوم بتوحيد كافة التمثيلات في شكل موحد هو عقدة Filter (points#0 > 9 OR team#1 = 'B').

يمتد هذا التطابق المعماري بطبيعة الحال إلى “الخطة الفيزيائية”، وهي الكود الفعلي الذي سيتم تشغيله فوق نوى المعالجة المركزية داخل الآلات الافتراضية لجافا (JVM). يُظهر فحص الخطة الفيزيائية استخدام نفس العوامل والمشغلات، مثل عامل التصفية المتزامن في الذاكرة (Scan + Filter) ودفع الشروط لأسفل (PushedFilters) بنفس الكيفية تماماً. يثبت هذا التحليل القاطع أنه من منظور الكفاءة الحسابية الصرفة وسرعة المعالجة واستهلاك الذاكرة ومعدلات استهلاك المعالج، لا يوجد أي فارق أدائي إطلاقاً بين كتابة الشرط كنص أو كتابته باستخدام المعامل الثنائي |، حيث يتولى محرك Catalyst إلغاء الفروق السطحية وتوحيد مسار التنفيذ النهائي لأقصى درجات الكفاءة الممكنة.

6.2 أمان الشيفرة وقابلية الصيانة وإعادة الهيكلة

إذا كان الأداء الحسابي النهائي متطابقاً، فإن المفاضلة الهندسية الحقيقية تحتكم إلى معايير هندسة البرمجيات: الأمان، وسهولة الصيانة، وقابلية التطوير على المدى البعيد. في هذا المضمار، يتفوق أسلوب الرمز الثنائي الموجه نحو الكائنات (col("points") > 9) | (col("team") == "B") تفوقاً ساحقاً على نظيره النصي، ولا سيما في المشاريع المؤسسية الضخمة التي يعمل عليها فرق برمجية متعددة وتتطلب آلاف الأسطر من الشيفرات المعقدة.

يبرز هذا التفوق في دعم بيئات التطوير المتكاملة لأدوات الإكمال التلقائي (Autocomplete) واكتشاف الأخطاء البرمجية لحظياً دون الحاجة إلى تشغيل الكود الفعلي. فعند كتابة كائنات الأعمدة، يمكن لأدوات التحليل الساكن التأكد من اتساق البنية وتوافق المتغيرات، وإطلاق تحذيرات فورية عند وجود أخطاء صياغية أو إهمال للأقواس. كما تصبح عمليات إعادة الهيكلة البرمجية (Refactoring)—مثل إعادة تسمية المتغيرات أو تمرير الأعمدة عبر دوال وسيطة—عملية آمنة ومؤتمتة بالكامل، مما يقلل من احتمالات تسرب الأخطاء الخفية إلى بيئات الإنتاج.

بالإضافة إلى ذلك، يوفر النهج الكائني مرونة منقطعة النظير في بناء الشروط المنطقية الديناميكية والبرمجة الوظيفية المتقدمة. ففي العديد من التطبيقات الواقعية، لا تكون معايير التصفية ثابتة أو معروفة مسبقاً أثناء كتابة الشيفرة، بل تعتمد على معاملات متغيرة تأتي من واجهات المستخدمين أو ملفات التكوين المتغيرة (JSON/YAML). يتيح نمط كائنات الأعمدة بناء شروط التصفية تدريجياً وتجميعها داخل مصفوفات أو حلقات برمجية ثم دمجها باستخدام المعامل | بسلاسة تامة، وهو ما يستحيل تنفيذه بالأسلوب النصي إلا عبر عمليات تقطيع وتوليد نصوص بالغة الهشاشة والتعقيد وعرضة للانهيار البرمجي لأتفه الأسباب التنسيقية.

6.3 تفضيلات الفرق الهندسية وتوحيد المعايير في بيئات العمل

تتباين الممارسات المفضلة داخل الفرق التقنية بناءً على الخلفيات التخصصية وطبيعة المهام الموكلة للمطورين. تميل الفرق ذات الخلفية التحليلية البحتة أو علماء البيانات القادمون من بيئات مستودعات البيانات التقليدية إلى استخدام التعبيرات النصية الشبيهة بـ SQL، نظراً لأنها توفر لهم ألفة بصرية فورية وتسمح لهم باختبار الفرضيات الإحصائية وتجربة الاستعلامات السريعة في أدوات الدفاتر التفاعلية (مثل Databricks أو Jupyter Notebooks) دون الانشغال بالقواعد الصارمة لإدارة الأقواس وتوزيع الكائنات.

على النقيض من ذلك، تضع الفرق الهندسية المسؤولة عن بناء خطوط نقل ومعالجة البيانات المستدامة (Data Pipelines) وتطبيقات الإنتاج الصارمة معايير تلزم المطورين بتبني الصياغة الكائنية المعتمدة على الرمز الثنائي | ودوال col() حصرياً. يُعزى هذا الإلزام إلى الرغبة في إخضاع الشيفرات البرمجية لاختبارات الوحدة المؤتمتة (Unit Testing)، وتسهيل عمليات المراجعة البرمجية التشاركية (Code Reviews)، وضمان اتساق النمط المتبع عبر كامل المستودع البرمجي للمؤسسة، مما يقلل من الديون التقنية (Technical Debt) ويسهل انضمام مهندسين جدد إلى الفرق دون الحاجة إلى فك طلاسم السلاسل النصية الطويلة والمعقدة.

لتحقيق التوازن الأمثل بين سهولة القراءة والمعايير الهندسية الصارمة، يُوصى بتوثيق الاستعلامات المعقدة توثيقاً دلالياً وافياً وتجزئتها برمجياً. فبدلاً من كتابة شرط ضخم يمتد لعدة أسطر في استدعاء تصفية واحد، يمكن للمطور تقسيم الشروط البديلة إلى متغيرات منطقية ذات أسماء دلالية واضحة (مثل: is_high_performer و is_target_region)، ثم دمج هذه المتغيرات المنطقية باستخدام المعامل | داخل دالة filter()، مما يحقق الجمع المثالي بين وضوح البنية المعمارية وجماليات التعبير البرمجي وسهولة الصيانة المستقبلية.

7. حالات الاستخدام المتقدمة: دمج المعامل “OR” مع شروط معقدة

7.1 الجمع بين المعاملين “AND” (&) و”OR” (|) في استعلامات مركبة

في بيئات الأعمال الحقيقية، نادراً ما تأتي متطلبات استخراج البيانات في صورة شروط بسيطة ومعزولة؛ بل غالباً ما تتطلب بناء استعلامات منطقية مركبة تدمج بين التحقق المتزامن لبعض المعايير عبر معامل العطف & (AND)، والخيارات البديلة الموسعة عبر معامل الفصل | (OR). يفرض هذا الدمج تحديات استثنائية تتعلق بتحديد الأولويات المنطقية وتفادي اللبس الدلالي الذي قد يؤدي إلى استرجاع بيانات خاطئة بالكامل إذا لم تُدار الأقواس بعناية فائقة.

تتمثل القاعدة الجوهرية في التعامل مع هذه الشروط المركبة في استيعاب التدرج الهرمي المنطقي؛ حيث يتمتع المعامل & نظرياً بأسبقية ضمنية تسبق المعامل |، مما يماثل أسبقية عملية الضرب على الجمع في العمليات الحسابية الجبرية. ومع ذلك، فإن الاعتماد على هذه الأسبقية التلقائية يعد من أسوأ الممارسات الهندسية، إذ يجعل الشيفرة عرضة لسوء الفهم من قِبل المطورين الآخرين ويزيد من احتمالات الخطأ. لذلك، يجب استخدام الأقواس التجميعية لتغليف الكتل المنطقية وتحديد تسلسل التقييم بوضوح لا يقبل التأويل.

لتوضيح هذا التعقيد عملياً، نفترض سيناريو استعلامياً يهدف إلى: “استخراج جميع لاعبي الفريق ‘A’ الذين حققوا أكثر من 15 نقطة، أو أي لاعب ينتمي للفريق ‘B’ شرط أن يكون قد قدم أكثر من 5 تمريرات حاسمة”. في هذه الحالة، لدينا كتلتان منطقيتان مستقلتان تُقيم كل منهما داخلياً عبر المعامل &، وترتبطان معاً خارجياً عبر المعامل |. تُصاغ هذه العملية المتقدمة برمجياً كما يلي:
complex_condition = ((col("team") == "A") & (col("points") > 15)) | ((col("team") == "B") & (col("assists") > 5))
df.filter(complex_condition).show()
يضمن هذا التنسيق المتداخل تقييم كل مجموعة من الشروط كوحدة واحدة غير قابلة للتجزئة قبل إجراء التقييم الفصلي النهائي، مما يحافظ على دقة البيانات المسترجعة ويمنع تسرب سجلات لا تنطبق عليها الضوابط المقررة.

7.2 تطبيق المعامل “OR” مع معالجة القيم المفقودة (Null / NaN Values)

تشكل القيم المفقودة (Null) أو غير الرقمية (NaN) أحد أكبر التحديات في معالجة البيانات الموزعة، حيث يمتلك محرك Spark سلوكاً منطقياً خاصاً عند التعامل معها كما أشرنا سابقاً في سياق المنطق الثلاثي القِيَم. تتجلى خطورة هذا السلوك عند تطبيق شروط التصفية البسيطة؛ فإذا كان لدينا شرط مثل col("points") > 10، فإن أي صف يحتوي على قيمة Null في عمود النقاط سيُقيم تلقائياً كقيمة خالية وليس كصواب، مما يؤدي إلى استبعاده فوراً من النتائج حتى وإن كانت بقية حقول الصف سليمة تماماً ومطلوبة للتحليل.

لمعالجة هذه المعضلة وضمان عدم إقصاء البيانات الحيوية دون قصد، يُستخدم المعامل | بالاقتران مع الدوال المخصصة لفحص الفراغ، مثل isNull() و isNotNull(). يتيح هذا الدمج توفير خيارات نجاة منطقية للصفوف؛ فإذا أردنا على سبيل المثال استرجاع السجلات التي حقق فيها اللاعبون أكثر من 10 نقاط، ولكننا في الوقت ذاته نريد الاحتفاظ بالسجلات التي لم تُسجل نقاطها بعد (ربما لمراجعتها يدوياً أو تعويضها لاحقاً بطرق إحصائية)، نقوم بصياغة الشرط البديل كالتالي:
condition_with_nulls = (col("points") > 10) | (col("points").isNull())
df.filter(condition_with_nulls).show()

تكمن القوة في هذا التركيب المنطقي في أن المعامل | يحمي الصفوف التي تحتوي على قيم مفقودة من الإقصاء التعسفي. فعندما يمر المحرك على صف يحمل قيمة خالية، يفشل الشق الأيسر في إعطاء صواب مؤكد، ولكن الشق الأيمن يتحقق بنجاح مطلق لأن الدالة isNull() تعيد صواباً صريحاً (True)، مما يجعل المحصلة الإجمالية للبوابة المنطقية صائبة، ويضمن بقاء الصف ضمن الإطار البياني المصفى دون انقطاع، وهو نمط حيوي لا غنى عنه في خطوط تنظيف وتأهيل البيانات (Data Cleansing Pipelines).

7.3 التكامل مع دوال السلاسل النصية والمطابقة النمطية

يمتد تطبيق المعامل | ليشمل التحليلات المتقدمة للسلاسل النصية عبر دمجه مع الدوال المتخصصة في مطابقة النصوص المدمجة في حزمة pyspark.sql.functions. في العديد من سيناريوهات استخراج البيانات غير المهيكلة جزئياً، يحتاج المطور إلى تصفية السجلات بناءً على وجود أنماط متفرقة أو كلمات مفتاحية متباينة داخل الأعمدة النصية، دون إرهاق النظام بعبارات استعلام متعددة أو تكرار استدعاءات التصفية التي قد تولد خطط تنفيذ ثقيلة وغير ضرورية.

يمكن دمج دوال مثل contains()، وstartswith()، وendswith()، والدالة النمطية الشبيهة بلغة SQL المعروفة بـ like() بسلاسة متناهية عبر المعامل المنطقي البديل |. على سبيل المثال، إذا كان لدينا عمود نصي يحتوي على تقارير الأداء الفني أو الملاحظات الوصفية للاعبين، ونريد استرجاع السجلات التي تتضمن كلمة “ممتاز” أو تبدأ بعبارة “واعد جداً”، تتم صياغة الاستعلام كالتالي:
text_condition = col("notes").contains("ممتاز") | col("notes").startswith("واعد جداً")
df.filter(text_condition).show()

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

8. بدائل متقدمة للمعامل “OR” للتعامل مع الشروط المتعددة

8.1 استخدام الدالة isin() كبديل فعال لسلاسل شروط OR المتكررة

من الأنماط البرمجية السيئة والشائعة التي يقع فيها المطورون عند محاولة مطابقة عمود واحد مع قائمة طويلة من القيم المقبولة، اللجوء إلى كتابة سلاسل مطولة ومتكررة من شروط المعامل |. على سبيل المثال، إذا أراد المطور تصفية السجلات للاعبين الذين ينتمون إلى الفرق ‘A’ أو ‘B’ أو ‘C’ أو ‘D’، فإن كتابة الشيفرة بالصورة التقليدية:
(col("team") == "A") | (col("team") == "B") | (col("team") == "C") | (col("team") == "D")
تعد صياغة شديدة الرداءة من منظور هندسة البرمجيات، حيث تجعل الكود متضخماً وصعب القراءة وعرضة للأخطاء الإملائية، فضلاً عن تحميل شجرة التعبيرات المنطقية داخل محرك Catalyst عقداً فرعية متكررة تثقل كاهل مرحلة التحليل الأولي.

تتمثل المقاربة الهندسية الفضلى والمثالية لمثل هذه الحالات في استخدام الدالة المدمجة isin()، والتي تطابق مشغل IN الشهير في لغة SQL. تتيح هذه الدالة تمرير قائمة بايثون عادية أو مجموعة من القيم كمعاملات مباشرة إلى عمود التصفية، ليقوم المحرك بفحص ما إذا كانت قيمة الحقل تنتمي إلى تلك المجموعة بكفاءة برمجية ومنطقية استثنائية:
target_teams = ["A", "B", "C", "D"]
efficient_df = df.filter(col("team").isin(target_teams))

من الناحية المعمارية، يتولى محرك Catalyst Optimizer تحويل استدعاء isin() داخلياً إلى تمثيل منطقي فائق التحسين يُعرف بـ InSet. يقوم هذا المشغل بإنشاء جدول تجزئة سريع (Hash Set) في الذاكرة للقيم المستهدفة، مما يحول تعقيد عملية البحث المنطقي لكل صف من تعقيد خطي نسبي يتناسب مع عدد شروط OR إلى تعقيد زمني شبه ثابت، مما يحقق قفزات نوعية في سرعة استرجاع البيانات وخاصة عندما تحتوي قائمة المطابقة على عشرات أو مئات العناصر.

8.2 توظيف الدوال التجميعية والتعبيرات النظامية (Regex)

في الحالات التي تتطلب تصفية السجلات بناءً على أنماط نصية معقدة ومتعددة الخيارات، يصبح استخدام المعامل | المتكرر غير عملي ومكلفاً للغاية. هنا تبرز القوة الفائقة للتعبيرات النظامية (Regular Expressions) عبر دالة rlike() المدمجة في كائنات أعمدة PySpark. تستقبل هذه الدالة نمطاً تعبيرياً شاملاً يدعم المعامل الفصلي المدمج في محركات التعبيرات النظامية (والذي يستخدم أيضاً رمز الخط الرأسي | داخل النمط النصي)، مما يتيح دمج خيارات بحث هائلة داخل تعبير برمجي واحد مقتضب.

على سبيل المثال، للبحث عن السجلات التي تبدأ بأسماء معينة أو تحتوي على أنماط ترميزية بديلة، يمكن صياغة التعبير بالشكل التالي:
regex_df = df.filter(col("team").rlike("^(A|B|D)$"))
يقوم هذا النمط بمطابقة السجلات التي تكون فيها قيمة الفريق حصراً إما ‘A’ أو ‘B’ أو ‘D’ باستخدام الآلية الداخلية لمحرك التعبيرات النظامية في جافا، مما يوفر على المطور كتابة شروط فصل متتالية.

علاوة على ذلك، توفر PySpark دوال متقدمة للتعامل مع البيانات المعقدة المضمنة في صورة مصفوفات (Arrays) داخل الصف الواحد، مثل دالة array_contains(). فبدلاً من فك وتفجير المصفوفة إلى صفوف مستقلة ثم تطبيق شروط OR المتكررة، يمكن استخدام هذه الدالة لفحص وجود العناصر البديلة مباشرة داخل الهيكل المعقد، مما يجنب النظام عمليات خلط البيانات الكارثية (Shuffling) ويحافظ على سلامة استهلاك الموارد الحسابية للعنقود.

8.3 بناء شروط OR ديناميكية باستخدام دالة functools.reduce

تفرض التطبيقات الصناعية المتقدمة في هندسة البيانات سيناريوهات تتولد فيها متطلبات التصفية بشكل ديناميكي كامل أثناء وقت التشغيل، كأن تأتي المعايير من مصفوفات غير محددة الطول مرسلة عبر طلبات واجهات البرمجة التطبيقية (APIs) أو مدخلات متغيرة من لوحات المتابعة (Dashboards). في مثل هذه الحالات، يستحيل على المطور كتابة شروط التصفية يدوياً في الكود، ويصبح البحث عن وسيلة لتجميع عدد غير محدود من الشروط المنطقية باستخدام المعامل | ضرورة حتمية.

توفر مكتبة بايثون القياسية أداة برمجية وظيفية غاية في الأناقة لحل هذه المعضلة المعمارية، وهي دالة reduce المضمنة في وحدة functools، بالاشتراك مع مشغل العمليات المنطقية operator.or_. تتيح هذه التوليفة استقبال قائمة من الشروط المنطقية المجردة وتطبيق المعامل المنطقي البديل بينها بصورة تراكمية وتكرارية لتوليد تعبير شرطي موحد وشامل دون أي تدخل يدوي.

يوضح المثال العملي التالي كيفية بناء دالة بايثون احترافية ومرنة تقبل قائمة ديناميكية من معايير التصفية وتدمجها برمجياً:

from functools import reduce
import operator
from pyspark.sql.functions import col

# تعريف قائمة ديناميكية من شروط التصفية المستقلة
conditions = [
    col("points") > 20,
    col("assists") > 8,
    col("team") == "A"
]

# تجميع الشروط ديناميكياً باستخدام معامل OR الوظيفي
dynamic_or_condition = reduce(operator.or_, conditions)

# تطبيق الشرط النهائي المركب على الإطار البياني
dynamic_filtered_df = df.filter(dynamic_or_condition)
dynamic_filtered_df.show()

تتمتع هذه الآلية بموثوقية معمارية مطلقة؛ فهي تقضي تماماً على مخاطر الأخطاء النحوية الناتجة عن إهمال الأقواس أو الدمج النصي غير المنضبط، كما أنها تضمن بقاء الكود البرمجي نظيفاً، ومرناً، وقابلاً للتوسع اللانهائي لاستيعاب أي عدد من الشروط المتغيرة بكفاءة استثنائية تتناغم تماماً مع الفلسفة الوظيفية لمحرك Apache Spark.

9. الأخطاء الشائعة وأفضل الممارسات البرمجية عند استخدام “OR”

9.1 خطأ إهمال الأقواس والتعامل مع استثناءات التحليل (Syntax Errors)

يحتل خطأ إهمال الأقواس الدائرية عند استخدام الرمز المنطقي الثنائي | المرتبة الأولى بلا منازع في قائمة الأخطاء الأكثر شيوعاً وإرباكاً للمطورين الجدد في بيئة PySpark. كما أوضحنا في التحليل النظري، يرجع هذا الخطأ الحتمي إلى الأسبقية الحسابية العليا للمعاملات الثنائية في لغة بايثون. تتجسد نتيجة هذا الخطأ برمجياً في شكل استثناءات صريحة تُلقى في وجه المطور أثناء وقت التشغيل، وتحديداً استثناء Py4JError أو استثناء بايثوني مباشر يفيد بعدم القدرة على تحويل الكائنات غير المتوافقة.

من الرسائل التحذيرية النمطية التي تظهر عند إهمال الأقواس، رسالة تشير إلى: Cannot resolve column name "... " due to data type mismatch أو الخطأ الشهير TypeError: unsupported operand type(s) for |: 'int' and 'Column'. تنشأ هذه الرسائل لأن المترجم يحاول تطبيق العملية الثنائية بين المعامل المباشر والرقم المحاذي له قبل إجراء عملية المقارنة، وهو تصرف برمجي غير مسموح به في هيكلية كائنات PySpark. لا يمكن حل هذه المشكلة إلا بالتطبيق الصارم لقاعدة: (شرط المقارنة الأول) | (شرط المقارنة الثاني)، دون أي تهاون نحوي.

أما عند استخدام الطريقة النصية (SQL-like expressions)، فإن الأخطاء تأخذ منحى مختلفاً يتعلق بالتحليل الدلالي لمحلل الاستعلامات، وتظهر عادة في صورة استثناء من نوع AnalysisException. يحدث هذا عندما ينسى المطور وضع علامات الاقتباس حول القيم النصية، كأن يكتب "team = B" بدلاً من "team = 'B'"، مما يجعل المحلل يعتقد خطأً أن الحرف B هو اسم لعمود آخر موجود في الجدول وليس قيمة نصية ثابتة، فينهار الاستعلام لفشله في العثور على عمود بهذا الاسم. لتفادي هذه الأخطاء، يُنصح بشدة بكتابة اختبارات أحادية (Unit Tests) مبكرة تغطي الحالات الحدية وتفحص صحة الشروط قبل دمجها في خطوط المعالجة الرئيسية.

9.2 الخلط بين دالتي filter() و where() في PySpark

يدور في أروقة المنتديات التقنية ومجتمعات هندسة البيانات نقاش دائم حول الفروق المحتملة بين دالتي filter() و where() في PySpark، والآثار الأدائية المترتبة على اختيار إحداهما دون الأخرى عند بناء استعلامات الشروط البديلة. ولحسم هذا اللبس بصورة قاطعة ومثبتة برمجياً: لا يوجد أي اختلاف على الإطلاق، سواء من الناحية الوظيفية، أو المعمارية، أو الأدائية بين الدالتين؛ فدالة where() هي مجرد اسم مستعار مطابق ونسخة كربونية صريحة (Alias) من دالة filter() داخل الكود المصدري لمكتبة Spark.

يعود وجود هاتين الدالتين المتطابقتين إلى الرغبة الاستراتيجية لمطوري Apache Spark في توفير بيئة مألوفة لمختلف المدارس البرمجية:

  • مدرسة البرمجة الوظيفية (Functional Programming): يفضل المطورون المنتمون إلى خلفيات برمجية مثل Scala، أو أولئك الذين اعتادوا على التعامل مع كائنات RDD الأصلية، استخدام المصطلح filter()، لأنه يتناغم مع دوال التصفية القياسية المألوفة في لغات البرمجة الوظيفية.
  • مدرسة قواعد البيانات والاستعلامات العلائقية (Relational SQL): يفضل مهندسو ومحللو البيانات القادمون من عالم قواعد البيانات ومستودعات SQL استخدام الدالة where()، نظراً لأنها تحاكي نفس الصياغة الذهنية لجملة SELECT ... WHERE ... الشهيرة في لغة SQL.

وعلى الرغم من تطابق الأداء الحسابي تماماً، فإن أفضل الممارسات الهندسية داخل المؤسسات التقنية تحث على ضرورة “توحيد الاصطلاح” داخل المشروع الواحد. إن الخلط العشوائي بين استدعاء filter() تارة وwhere() تارة أخرى داخل نفس الملف البرمجي يعطي انطباعاً بضعف الانضباط الهيكلي، لذلك يُفضل اختيار أحد الأسلوبين وتثبيته كمعيار قياسي في أدلة النمط البرمجي (Style Guides) الخاصة بالفريق لضمان اتساق وجمالية الشيفرة المصدرية.

9.3 أفضل ممارسات التحسين لتسريع الاستعلامات وتجنب الاختناقات

يتطلب تحقيق أقصى استفادة من محرك Spark عند استخدام المعامل “OR” اتباع حزمة من أفضل الممارسات الهندسية التي تستهدف تخفيف الأعباء الحسابية وتفادي الاختناقات الأدائية في الذاكرة ووحدات المعالجة. تأتي في مقدمة هذه الممارسات قاعدة “ترتيب الانتقائية” (Selectivity Ordering)؛ فعند صياغة شروط التصفية البديلة، يجب وضع الشروط ذات الانتقائية العالية—أي الشروط الأكثر قدرة على إقصاء أعداد هائلة من الصفوف غير المطابقة—في الطرف الأيسر والأول من التعبير المنطقي. يتيح هذا الترتيب الاستفادة القصوى من آلية التقييم قصير الدائرة، حيث يتم حسم النتيجة الإيجابية للصفوف بسرعة دون الحاجة لاستهلاك دورات المعالج في تقييم الشروط اللاحقة الأكثر بطئاً.

من المحاذير المعمارية الكبرى أيضاً تجنب استدعاء الدوال المعرفة من قِبل المستخدم غير المدمجة (Python UDFs) داخل شروط المعامل “OR”. تؤدي دوال UDFs التقليدية المكتوبة بلغة بايثون إلى كسر خطط التحسين المترجمة داخلياً في محرك Catalyst، وتجبر النظام على تسلسل ونقل البيانات (Serialization/Deserialization) بين الآلة الافتراضية لجافا (JVM) ومفسر بايثون ذهاباً وإياباً، مما يسبب تدهوراً دراماتيكياً في سرعة المعالجة. بدلاً من ذلك، يجب الاعتماد حصرياً على الدوال المدمجة (Native Functions) المتوفرة في حزمة pyspark.sql.functions والمحسنة للعمل مباشرة فوق الذاكرة بمحرك Tungsten فائق السرعة.

أخيراً، يكتسي التخزين المؤقت الذكي (Caching / Persisting) أهمية استراتيجية بالغة. إذا كان الإطار البياني الناتج عن تصفية الشروط البديلة سيُستخدم بشكل متكرر في مراحل لاحقة من خط المعالجة—مثل إجراء عمليات تجميعية متعددة، أو تدريب نماذج تعلم آلي—فإن استدعاء دالة persist() أو cache() على الـ DataFrame المصفى يُعد خطوة جوهرية. يمنع التخزين المؤقت محرك Spark من إعادة تنفيذ استعلام التصفية وشجرة التعبيرات المنطقية المعقدة في كل مرة يُستدعى فيها إجراء نهائي، مما يقلل بشكل ملموس من زمن المعالجة الإجمالي ويضمن الاستخدام الأمثل لموارد العنقود الحسابي.

10. تطبيقات عملية ودراسات حالة واقعية في تحليل البيانات الضخمة

10.1 تصفية سجلات سلوك المستخدمين في الأنظمة التفاعلية الضخمة

تتعامل المنصات الرقمية التفاعلية العملاقة—مثل شبكات التواصل الاجتماعي ومنصات التجارة الإلكترونية الدولية—مع مليارات الأحداث اليومية المتدفقة (Clickstream Logs) التي تسجل كل نقرة وتفاعل يقوم به المستخدمون حول العالم. تمثل هذه التدفقات كتل بيانات ضخمة تتطلب تصفية فائقة الدقة لعزل الأنماط السلوكية التي تهم فرق تطوير المنتجات والتحليلات التسويقية، وتحديد الفئات المستهدفة بالحملات الموجهة دون إبطاء البنية التحتية.

في هذا السياق العملي، يُستخدم المعامل “OR” بشكل مكثف لعزل جلسات المستخدمين التي تتطلب معالجة خاصة. لنفترض سيناريو تسويقياً يسعى لاستهداف العملاء الذين يظهرون نية شراء مؤكدة؛ يتم تعريف هؤلاء العملاء إما بكونهم قضوا أكثر من 300 ثانية في تصفح صفحة الدفع والمنتجات المميزة، أو أنهم أضافوا سلعاً إلى سلة المشتريات تتجاوز قيمتها الإجمالية 200 دولار، بغض النظر عن مدة التصفح. يتم بناء استعلام التصفية الموزع لتحديد هذه الفئة المستهدفة واستبعاد ملايين الزيارات العابرة غير المنتجة فوراً من خطوط المعالجة التحليلية.

يمتد هذا النمط المنطقي أيضاً إلى معالجة البيانات المتدفقة في الوقت الحقيقي عبر تقنية Spark Structured Streaming. حيث يتم تغذية المحرك بتدفقات لحظية من الأحداث، ويقوم المعامل “OR” بفحص السجلات اللحظية وفق الشروط البديلة وتوجيه الجلسات المطابقة فوراً إلى محركات الإشعارات الفورية أو أنظمة التوصيات الشخصية، مما يمنح الشركات قدرة استثنائية على التفاعل اللحظي مع سلوكيات المستهلكين بأقل زمن استجابة ممكن.

10.2 رصد وتحديد الحالات الشاذة (Anomaly Detection) في المعاملات المالية

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

يتجلى دور المعامل “OR” هنا كأداة حاسمة لتوسيع شبكة الأمان الرقابية. فالاحتيال المالي لا يتخذ شكلاً واحداً، بل يظهر عبر أنماط وسلوكيات شاذة متباينة ومتعددة الأوجه. ولذلك، تصمم قواعد التصفية لالتقاط أي معاملة تحقق واحداً على الأقل من معايير الخطورة العالية؛ مثل أن تتجاوز قيمة الحوالة المالية مبلغ 10,000 دولار بصورة مفاجئة، أو أن يتم تنفيذ المعاملة من موقع جغرافي يختلف جذرياً عن الموقع المعتاد للعميل خلال نافذة زمنية يستحيل فيها السفر فيزيائياً، أو أن تتم العملية في أوقات متأخرة جداً من الليل بالتزامن مع تغيير كلمة المرور حديثاً.

تتم ترجمة هذه القواعد المصرفية المعقدة داخل PySpark إلى تعبيرات فصل منطقي مركبة تضم معاملات | المتعددة، وتُطبق فوق تدفقات المعاملات المالية الموزعة. يتيح هذا النهج لعناقيد Spark عزل المعاملات المشبوهة فوراً وإرسالها إلى أنظمة التجميد المؤقت وفرق التدقيق البشري، مع ضمان استمرار المعاملات الطبيعية الأخرى بسلاسة تامة دون تعطيل لتجربة المستخدمين الشرعيين، مما يحقق التوازن المنشود بين الأمان المصرفي الصارم والفاعلية التشغيلية العالية.

10.3 إعداد وتجهيز البيانات لخطوط تدريب نماذج تعلم الآلة (ETL Pipelines)

تُمثل مرحلة استخراج وتحويل وتحميل البيانات (ETL) وتجهيزها الركيزة الأساسية التي تسبق بناء وتدريب نماذج التعلم الآلي والذكاء الاصطناعي على النطاق المؤسسي. في هذه المرحلة الحساسة، يواجه مهندسو البيانات وعلماء الذكاء الاصطناعي تحديات تتعلق بعدم توازن الفئات (Class Imbalance) وتلوث مجموعات البيانات بالعينات غير النمطية أو المشوهة التي قد تفسد عملية استخلاص الخصائص وتضر بصلابة الخوارزميات التنبؤية.

يُوظف المعامل “OR” في هذه الخطوط كمرشح استراتيجي متعدد الاتجاهات لتكوين عينات التدريب المتوازنة. فعند بناء نموذج لتصنيف المخاطر الائتمانية على سبيل المثال، قد يحتاج المهندسون إلى تضمين كافة العملاء الذين تعثروا تاريخياً في السداد، إلى جانب عينات متكافئة من العملاء ذوي الدخول المالية المتدنية أو أولئك الذين يحملون ديوناً بنكية متعددة، لضمان تعرض النموذج التنبؤي لجرعات كافية من الحالات الحدية التي تساعده على تعميم قراراته. يُصاغ شرط التصفية باستخدام المعامل | ليجمع هذه الفئات المتباينة من مصادر متعددة في إطار بياني تدريبي موحد ومهيأ للدخول في مراحل التحجيم وهندسة الخصائص.

فضلاً عن ذلك، يضمن التوثيق الدقيق لشروط التصفية المنطقية في كود PySpark الحفاظ على “نسب البيانات” (Data Lineage) وإمكانية تتبع الأثر الرقابي. ففي القطاعات الحيوية كالرعاية الصحية والتمويل، تفرض الهيئات التنظيمية تقديم أدلة وإثباتات قطعية حول كيفية اختيار العينات التدريبية، وكيف تم استبعاد السجلات غير المؤهلة. تتيح الصياغة الكائنية الصريحة لشروط التصفية باستخدام PySpark تسجيل وتدقيق هذه المعايير الرياضية بالكامل ضمن مسار إدارة التجارب الحوسبية، مما يعزز من شفافية وموثوقية نماذج الذكاء الاصطناعي المنشورة في بيئات الإنتاج الحقيقية.

خاتمة

استعرضنا في هذا الدليل الشامل والمفصل الأبعاد المعمارية والبرمجية لاستخدام المعامل المنطقي البديل “OR” ضمن إطار عمل معالجة البيانات الموزعة PySpark. بدأت رحلتنا من تفكيك الأسس النظرية للجبر البولياني وتطبيقاته على الجداول الموزعة في ظل المنطق الثلاثي القِيَم للتعامل مع البيانات الخالية، وصولاً إلى استكشاف الكيفية التي يقوم بها محرك التحسين Catalyst بتحويل الشروط المنطقية المجردة إلى خطط تنفيذ فيزيائية متطورة تطبق تقنيات دفع الشروط للأسفل والتوليد الديناميكي للأكواد البرمجية المحسنة.

أبرزت المقارنة المعمارية بين الأسلوب النصي الشبيه بلغة SQL والأسلوب الكائني المعتمد على الرمز الثنائي | أن كلا الأسلوبين يتطابقان تماماً في الأداء الحسابي النهائي وسرعة التنفيذ، مما يترك خيار المفاضلة لمعايير هندسة البرمجيات وجودة التصميم؛ حيث يفرض الرمز الثنائي | نفسه كمعيار ذهبي لتطبيقات الإنتاج الضخمة بفضل توافقه مع أدوات التحليل الساكن، وقابليته العالية لإعادة الهيكلة، ودعمه الفريد لبناء الشروط التفاعلية الديناميكية. كما ناقشنا البدائل المتقدمة كدالة isin() والتعبيرات النظامية، وأوضحنا الاستراتيجيات المثلى لتفادي الأخطاء الشائعة المرتبطة بإهمال الأقواس وإدارة أسبقية العمليات في لغة بايثون.

ختاماً، لا تقتصر مهارة تصفية البيانات في بيئة الحوسبة الموزعة على حفظ الصيغ النحوية المباشرة، بل تقتضي وعياً عميقاً بالآثار البنيوية التي يتركها كل سطر برمجي على إدارة موارد العناقيد الحسابية وتدفق البيانات عبر الشبكات. إن الفهم الدقيق لديناميكيات المعاملات المنطقية وفي مقدمتها المعامل “OR” يُمكن مهندس البيانات من كتابة حلول تتسم بالصلابة المعمارية، والأناقة البرمجية، والكفاءة الفائقة، مما يضمن تحويل طوفان البيانات الضخمة المتدفقة إلى أصول معرفية دقيقة وقابلة للاستثمار المستدام.

المراجع

  • Armbrust, M., Xin, R. S., Lian, C., Huai, Y., Liu, D., Bradley, J. K., Meng, X., Kaftan, T., Franklin, M. J., Ghodsi, A., & Zaharia, M. (2015). Spark SQL: Relational data processing in Spark. In Proceedings of the 2015 ACM SIGMOD International Conference on Management of Data (pp. 1383–1394). Association for Computing Machinery. https://doi.org/10.1145/2723372.2742797
  • Chambers, B., & Zaharia, M. (2018). Spark: The definitive guide: Big data processing made simple. O’Reilly Media.
  • Karau, H., & Warren, R. (2017). High performance Spark: Best practices for scaling and optimizing Apache Spark. O’Reilly Media.
  • Zaharia, M., Chowdhury, M., Das, T., Dave, A., Ma, J., McCauley, M., Franklin, M. J., Shenker, S., & Stoica, I. (2012). Resilient distributed datasets: A fault-tolerant abstraction for in-memory cluster computing. In Proceedings of the 9th USENIX Conference on Networked Systems Design and Implementation (NSDI 12) (pp. 15–28). USENIX Association.
★

تقييم هذا المحتوى

5.0 / 5 • 7 تقييمات

اقتباس هذا المقال

looti, M. (2026, أكتوبر 24). كيفية استخدام المعامل “OR” في PySpark (مع أمثلة). عرب سايكلوجي. https://arabpsychology.com/statistics/how-to-use-or-operator-in-pyspark-with-examples/
looti, Mohammed. “كيفية استخدام المعامل “OR” في PySpark (مع أمثلة).” عرب سايكلوجي, 24 أكتوبر 2026, https://arabpsychology.com/statistics/how-to-use-or-operator-in-pyspark-with-examples/.
looti, Mohammed. “كيفية استخدام المعامل “OR” في PySpark (مع أمثلة).” عرب سايكلوجي. أكتوبر 24, 2026. https://arabpsychology.com/statistics/how-to-use-or-operator-in-pyspark-with-examples/.