تحديات البحث باللغة العربية في التجارة الإلكترونية السورية

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

ومع ذلك، فإن طرق البحث التقليدية في قواعد البيانات SQL باستخدام صيغة الملاءمة البسيطة LIKE '%query%' تفشل غالباً في تقديم تجربة بحث عربية فعالة، حيث تعاني من البطء الشديد في قواعد البيانات الكبيرة، ولا تدعم ترتيب النتائج حسب ملاءمتها، بالإضافة إلى عجزها عن معالجة الخصائص الفريدة للغة العربية مثل:

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

وعلى الرغم من أن محركات البحث المتخصصة مثل Elasticsearch أو Solr تحل هذه المشاكل بكفاءة، إلا أنها تتطلب حجماً كبيراً من ذاكرة الوصول العشوائي (RAM) وبنية تحتية مستقلة للسيرفرات. وبالنسبة للمشاريع السورية الناشئة والشركات الصغيرة والمتوسطة التي تعتمد على سيرفرات سحابية اقتصادية بمواصفات محدودة (مثل 1 أو 2 جيجابايت رام)، فإن تشغيل محرك بحث مبني على لغة Java إلى جانب سيرفر التطبيق الأساسي يعد مكلفاً وغير عملي.

وهنا توفر قاعدة بيانات PostgreSQL بديلاً ممتازاً ومدمجاً وهو: البحث النصي الكامل (Full-Text Search). فمن خلال الاستفادة من ميزات FTS الأصلية في PostgreSQL، يمكنك بناء محرك بحث سريع، مرن، ودقيق لغوياً للغة العربية يعمل مباشرة داخل قاعدة بياناتك الأساسية، دون الحاجة لأي بنية تحتية إضافية.

فيما يلي دليل هندسي عملي لإعداد وتخصيص البحث النصي الكامل باللغة العربية في PostgreSQL.

---

الخطوة الأولى: كتابة دالة لتطبيع النصوص العربية

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

قم بإنشاء دالة PL/pgSQL التالية في قاعدة بياناتك:

CREATE OR REPLACE FUNCTION normalize_arabic(input_text TEXT)
RETURNS TEXT AS $$
DECLARE
    normalized TEXT;
END;
$$ LANGUAGE plpgsql IMMUTABLE;

(ملاحظة: سنقوم بكتابة تفاصيل الدالة البرمجية الكاملة والموثوقة بلغة SQL):

CREATE OR REPLACE FUNCTION normalize_arabic(input_text TEXT)
RETURNS TEXT AS $$
DECLARE
    normalized TEXT;
BEGIN
    IF input_text IS NULL THEN
        RETURN '';
    END IF;

    -- تحويل الحروف الإنجليزية إلى صغيرة (إذا وجدت) وإزالة الفراغات الزائدة
    normalized := lower(trim(input_text));

    -- 1. إزالة جميع حركات التشكيل العربية
    -- تشمل الفتحة، الضمة، الكسرة، السكون، الشدة، والتنوين
    normalized := regexp_replace(normalized, '[\u064B-\u0652\u0653\u0670]', '', 'g');

    -- 2. توحيد أشكال الهمزة والألف (أ، إ، آ إلى ا)
    normalized := regexp_replace(normalized, '[أإآ]', 'ا', 'g');

    -- 3. تحويل التاء المربوطة إلى هاء (ة إلى ه)
    -- يساعد هذا في مطابقة "أجهزة" مع "اجهزه"
    normalized := regexp_replace(normalized, 'ة', 'ه', 'g');

    -- 4. تحويل الألف المقصورة إلى ياء (ى إلى ي)
    -- يساعد في مطابقة "مشفى" مع "مشفي"
    normalized := regexp_replace(normalized, 'ى', 'ي', 'g');

    -- 5. إزالة أل التعريف من بداية الكلمات (اختياري ومفيد جداً للمتاجر الإلكترونية)
    -- نزيل "ال" فقط إذا كانت في بداية الكلمة باستخدام حدود الكلمات في التعابير النمطية (\y)
    normalized := regexp_replace(normalized, '\yال([أ-ي]+)', '\1', 'g');

    RETURN normalized;
END;
$$ LANGUAGE plpgsql IMMUTABLE;

> [!TIP] > من الضروري تعريف الدالة كـ IMMUTABLE (غير قابلة للتغيير). فهذا يخبر PostgreSQL أن الدالة ستعطي دائماً نفس النتيجة لنفس المدخلات، مما يسمح باستخدامها بأمان في الفهارس والأعمدة المولدة تلقائياً.

---

الخطوة الثانية: إنشاء إعدادات مخصصة للبحث العربي

تستخدم PostgreSQL إعدادات للبحث النصي من أجل تقسيم الجمل إلى كلمات (Tokens) وتمريرها عبر القواميس المعالجة. ونظراً لأن بعض البيئات أو مزودي الخدمات السحابية لا يدعمون تنصيب قواميس عربية متقدمة خارج الصندوق، سنقوم بإنشاء إعداد مخصص يرث القاموس البسيط simple ويطبق عليه دالة التطبيع التي كتبناها.

نفذ الأوامر التالية لتعريف إعدادات البحث المخصصة:

-- 1. إنشاء تكوين بحث نصي جديد منسوخ من التكوين البسيط
-- التكوين البسيط يحول الكلمات إلى حروف صغيرة ويقسمها فقط دون تطبيق قواعد لغات أخرى
CREATE TEXT SEARCH CONFIGURATION arabic_normalized (COPY = simple);

-- 2. تعيين معالجة الكلمات لتمر عبر القاموس البسيط
-- يضمن هذا عدم تطبيق أي اشتقاقات خاطئة خاصة باللغة الإنجليزية على الكلمات العربية
ALTER TEXT SEARCH CONFIGURATION arabic_normalized
    ALTER MAPPING FOR asciiword, word, numword
    WITH simple;

---

الخطوة الثالثة: تصميم مخطط الجدول وتخزين متجهات البحث

للحفاظ على سرعة الاستجابة القصوى لقاعدة البيانات، يجب تجنب استدعاء دالة التطبيع وحساب متجه البحث tsvector لحظياً أثناء كتابة العميل للكلمات في شريط البحث. يؤدي الحساب اللحظي إلى إجبار قاعدة البيانات على فحص كافة السطور (Full Table Scan)، وهو ما يسبب بطء البحث مع زيادة المنتجات.

الحل الأمثل هو تخزين متجه البحث مسبقاً داخل الجدول كعمود مولّد ومخزن تلقائياً GENERATED ALWAYS AS ... STORED (وهي ميزة مدعومة بدءاً من إصدار PostgreSQL 12)، حيث يتم تحديث العمود تلقائياً عند إضافة أو تعديل أي منتج.

إليك مخطط جدول المنتجات كمثال:

CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    sku VARCHAR(50) UNIQUE NOT NULL,
    title TEXT NOT NULL,
    description TEXT,
    category VARCHAR(100),
    price NUMERIC(10, 2) NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    
    -- عمود متجه البحث الذي يدمج الاسم والتصنيف والوصف بعد التطبيع
    search_vector tsvector GENERATED ALWAYS AS (
        to_tsvector('arabic_normalized', 
            coalesce(normalize_arabic(title), '') || ' ' ||
            coalesce(normalize_arabic(category), '') || ' ' ||
            coalesce(normalize_arabic(description), '')
        )
    ) STORED;
);

أما إذا كنت تستخدم إصداراً أقدم من PostgreSQL 12، فيمكنك تحقيق النتيجة ذاتها عن طريق إنشاء عمود عادي واستخدام "مثير" (Trigger) لتحديثه قبل كل عملية حفظ:

-- للإصدارات الأقدم من PostgreSQL 12
ALTER TABLE products ADD COLUMN search_vector tsvector;

CREATE OR REPLACE FUNCTION products_search_vector_trigger()
RETURNS TRIGGER AS $$
BEGIN
    NEW.search_vector := to_tsvector('arabic_normalized', 
        coalesce(normalize_arabic(NEW.title), '') || ' ' ||
        coalesce(normalize_arabic(NEW.category), '') || ' ' ||
        coalesce(normalize_arabic(NEW.description), '')
    );
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trg_products_search_vector_update
    BEFORE INSERT OR UPDATE ON products
    FOR EACH ROW EXECUTE FUNCTION products_search_vector_trigger();

---

الخطوة الرابعة: إنشاء الفهرس لتحسين الأداء

لإجراء عمليات البحث في زمن يقل عن جزء من الملي ثانية، يجب علينا فهرسة عمود search_vector باستخدام الفهرس المعكوس العام GIN (Generalized Inverted Index). يقوم فهرس GIN بوضع خريطة تربط كل كلمة دلالية بالصفوف التي تحتوي عليها مباشرة، مما يلغي تماماً الحاجة لمسح صفوف الجدول صفاً صفاً.

قم بإنشاء الفهرس باستخدام الأمر التالي:

CREATE INDEX idx_products_search_vector ON products USING gin(search_vector);

باستخدام هذا الفهرس، يمكن لـ PostgreSQL عرض نتائج البحث في أجزاء من الملي ثانية، حتى لو كان المتجر يحتوي على مئات الآلاف من المنتجات.

---

الخطوة الخامسة: كتابة استعلامات البحث وترتيب النتائج

عند كتابة استعلام البحث، يجب معالجة الكلمات التي يدخلها المستخدم وتمريرها عبر نفس دالة التطبيع.

سنقوم بإنشاء دالة مساعدة تأخذ النص المدخل من العميل وتقوم بتحويل الفراغات بين الكلمات إلى معامل المنطق & (بمعنى "و") لبناء استعلام بحث سليم برمجياً:

CREATE OR REPLACE FUNCTION parse_arabic_query(search_query TEXT)
RETURNS tsquery AS $$
DECLARE
    clean_query TEXT;
    formatted_query TEXT;
BEGIN
    -- تطبيع النص المدخل
    clean_query := normalize_arabic(search_query);
    
    -- استبدال المسافات الزائدة بمعامل البحث المشترك &
    -- مثلاً: "اجهزة ذكية" تتحول إلى "اجهزه & ذكيه"
    formatted_query := regexp_replace(trim(clean_query), '\s+', ' & ', 'g');
    
    RETURN to_tsquery('arabic_normalized', formatted_query);
EXCEPTION
    -- حالة احتياطية في حال حدوث أي خطأ في الصياغة
    WHEN OTHERS THEN
        RETURN plainto_tsquery('arabic_normalized', search_query);
END;
$$ LANGUAGE plpgsql IMMUTABLE;

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

SELECT 
    id,
    sku,
    title,
    price,
    -- حساب مدى الملاءمة (ترتيب أعلى للكلمات الأكثر تقارباً)
    ts_rank_cd(search_vector, query) AS relevance,
    -- توليد مقتطف نصي يبرز الكلمة المطابقة في الوصف
    ts_headline('arabic_normalized', description, query, 
        'StartSel = <span class="highlight">, StopSel = </span>, MaxWords=25, MinWords=15'
    ) AS snippet
FROM 
    products, 
    parse_arabic_query('أجهزة ذكية') query
WHERE 
    search_vector @@ query
ORDER BY 
    relevance DESC, 
    created_at DESC
LIMIT 12;

---

تقييم جودة نتائج البحث

لنقارن الفارق بين الاستعلامات التقليدية ونظام البحث النصي المطور والمحسن:

| نص استعلام المستخدم | التطابق باستخدام LIKE التقليدي | التطابق باستخدام FTS المطور | السبب والتحليل | | :--- | :--- | :--- | :--- | | اجهزه | ❌ يفشل (مخزن باسم الأجهزة بالهمزة وأل التعريف) | ✅ يتطابق (يتم تطبيع الكلمتين لـ اجهزه وحذف أل التعريف) | تسوية السوابق ومعالجة تشابه الحروف. | | أَجْهِزَةٌ | ❌ يفشل (مخزن بدون تشكيل) | ✅ يتطابق (يتم تجريد حركات التشكيل تماماً) | إزالة حركات التشكيل من النص المستعلم والنص المخزن. | | ذكية | ❌ يفشل (مخزن بصيغة ذكيه بالهاء) | ✅ يتطابق (يتم تحويل ة إلى ه) | حل مشاكل الأخطاء الإملائية الشائعة لدى المستخدمين. |

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

---

الخلاصة والخطوات القادمة

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

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

هل تبحث عن تحسين أداء قواعد بياناتك الحالية، دمج بوابات دفع إلكترونية محلية، أو بناء تطبيق ويب مخصص لشركتك؟ تواصل مع Dragonfly Soft اليوم لمناقشة مشروعك القادم مع فريقنا الهندسي في حلب وتخطيط بنيتك الرقمية القادمة.