MySQL وتصميم قواعد البيانات

البحث النصي الكامل

13 دقيقة الدرس 18 من 40

البحث النصي الكامل

البحث النصي الكامل في MySQL يسمح لك بإجراء عمليات بحث نصية معقدة بشكل أسرع وأكثر فعالية من استخدام أنماط LIKE. في هذا الدرس، سنستكشف فهارس FULLTEXT وصيغة MATCH AGAINST لقدرات البحث النصي القوية.

ما هو البحث النصي الكامل؟

البحث النصي الكامل محسّن للبحث في كميات كبيرة من البيانات النصية. إنه أكثر كفاءة بكثير من مطابقة الأنماط باستخدام LIKE:

بحث LIKE التقليدي (بطيء): SELECT * FROM articles WHERE content LIKE '%database%' OR content LIKE '%performance%' OR content LIKE '%optimization%'; -- المشكلة: فحص جدول كامل، لا يمكن استخدام فهرس عادي البحث النصي الكامل (سريع): SELECT * FROM articles WHERE MATCH(content) AGAINST('database performance optimization'); -- يستخدم فهرس FULLTEXT، يعيد نتائج مرتبة حسب الصلة
الميزة الرئيسية: البحث النصي الكامل يعيد النتائج مرتبة حسب درجة الصلة، يتعامل تلقائياً مع حدود الكلمات، ويمكنه البحث في أعمدة متعددة في وقت واحد.

إنشاء فهارس FULLTEXT

يمكن إنشاء فهارس FULLTEXT فقط على أعمدة CHAR و VARCHAR و TEXT:

فهرس FULLTEXT لعمود واحد

-- إنشاء جدول مع فهرس FULLTEXT CREATE TABLE articles ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(255), content TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FULLTEXT KEY ft_content (content) ); -- إضافة فهرس FULLTEXT إلى جدول موجود ALTER TABLE articles ADD FULLTEXT INDEX ft_content (content); -- أو باستخدام CREATE INDEX CREATE FULLTEXT INDEX ft_content ON articles(content);

فهرس FULLTEXT متعدد الأعمدة

-- البحث عبر أعمدة متعددة CREATE TABLE articles ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(255), description TEXT, content TEXT, FULLTEXT KEY ft_all (title, description, content) ); -- هذا يسمح بالبحث عبر الأعمدة الثلاثة دفعة واحدة SELECT * FROM articles WHERE MATCH(title, description, content) AGAINST('MySQL optimization');
أفضل ممارسة: أنشئ فهارس FULLTEXT منفصلة لسيناريوهات بحث مختلفة. واحد لعمليات البحث في العنوان فقط، آخر للمحتوى فقط، وثالث للبحث في جميع الحقول معاً.

صيغة MATCH AGAINST

يتم استخدام جملة MATCH AGAINST للاستعلام عن فهارس FULLTEXT:

الصيغة الأساسية: SELECT * FROM table WHERE MATCH(column1, column2, ...) AGAINST('search terms'); قواعد مهمة: 1. الأعمدة في MATCH() يجب أن تطابق تماماً فهرس FULLTEXT 2. لا يمكن خلط أعمدة MATCH من فهارس FULLTEXT مختلفة 3. يعيد الصفوف مرتبة حسب درجة الصلة (الأعلى أولاً)

أوضاع البحث النصي الكامل

تقدم MySQL ثلاثة أوضاع بحث نصي كامل، كل منها بقدرات مختلفة:

1. وضع اللغة الطبيعية (الافتراضي)

-- بحث اللغة الطبيعية (افتراضي) SELECT *, MATCH(title, content) AGAINST('database performance') as relevance FROM articles WHERE MATCH(title, content) AGAINST('database performance') ORDER BY relevance DESC; كيف يعمل: - يبحث عن أي من الكلمات: "database" أو "performance" - يتجاهل تلقائياً الكلمات الشائعة جداً (stopwords) - يعيد النتائج مرتبة حسب الصلة - الكلمات بين علامات الاقتباس تُعامل كعبارات أمثلة المطابقات: ✓ "Database optimization techniques" ✓ "Improving query performance" ✓ "Database and performance tuning" ✗ "Getting started with MySQL" (لا كلمات مطابقة)

2. الوضع المنطقي

الوضع المنطقي يمنحك تحكماً دقيقاً في سلوك البحث:

-- بحث الوضع المنطقي SELECT * FROM articles WHERE MATCH(title, content) AGAINST('+database +performance' IN BOOLEAN MODE); العوامل المنطقية: + الكلمة يجب أن تكون موجودة مثال: +database يطابق: "Database design" ✓ لا: "SQL queries" ✗ - الكلمة يجب ألا تكون موجودة مثال: +database -MySQL يطابق: "PostgreSQL database" ✓ لا: "MySQL database" ✗ * حرف بدل (بادئة كلمة) مثال: optim* يطابق: "optimization", "optimize", "optimal" ✓ "" عبارة دقيقة مثال: "database design" يطابق: "...database design..." ✓ لا: "database and design" ✗ > زيادة صلة الكلمة مثال: +database >performance "performance" يزيد درجة الصلة < تقليل صلة الكلمة مثال: +database <legacy "legacy" يقلل درجة الصلة () التجميع مثال: +(database mysql) +performance يجب أن يحتوي على (database أو mysql) و performance

أمثلة الوضع المنطقي

-- يجب أن يحتوي على "database" و "performance" WHERE MATCH(content) AGAINST('+database +performance' IN BOOLEAN MODE); -- يجب أن يحتوي على "database"، يجب ألا يحتوي على "Oracle" WHERE MATCH(content) AGAINST('+database -Oracle' IN BOOLEAN MODE); -- بحث حرف بدل: optimization, optimize, optimal WHERE MATCH(content) AGAINST('optim*' IN BOOLEAN MODE); -- بحث عبارة دقيقة WHERE MATCH(content) AGAINST('"database performance"' IN BOOLEAN MODE); -- معقد: يجب أن يحتوي على MySQL، يفضل performance، يستبعد deprecated WHERE MATCH(content) AGAINST('+MySQL >performance -deprecated' IN BOOLEAN MODE); -- إما database أو performance، لكن ليس كلاهما مطلوبين WHERE MATCH(content) AGAINST('database performance' IN BOOLEAN MODE); -- يجب أن يحتوي على database و (optimization أو tuning) WHERE MATCH(content) AGAINST('+database +(optimization tuning)' IN BOOLEAN MODE);

3. وضع توسيع الاستعلام

توسيع الاستعلام يجري بحثاً من مرحلتين للعثور على مصطلحات ذات صلة:

-- بحث توسيع الاستعلام SELECT * FROM articles WHERE MATCH(content) AGAINST('database' WITH QUERY EXPANSION); كيف يعمل: المرحلة 1: البحث عن "database" المرحلة 2: العثور على كلمات شائعة في نتائج المرحلة 1، البحث مرة أخرى مثال: البحث الأولي: "database" نتائج المرحلة 1 تحتوي على: MySQL, SQL, tables, queries المرحلة 2 تبحث عن: "database MySQL SQL tables queries" متى نستخدم: ✓ المستخدم يدخل مصطلحات بحث قصيرة جداً ✓ تريد العثور على محتوى ذي صلة ✓ التعامل مع المرادفات والمفاهيم ذات الصلة تحذير: يمكن أن يعيد نتائج أقل صلة إذا كانت مجموعة البيانات متنوعة استخدم بحذر - اختبر مع بياناتك الفعلية

تسجيل الصلة

تحسب MySQL درجة صلة لكل نتيجة. الدرجات الأعلى تشير إلى تطابقات أفضل:

-- الحصول على درجات الصلة SELECT id, title, MATCH(title, content) AGAINST('MySQL performance') as relevance_score FROM articles WHERE MATCH(title, content) AGAINST('MySQL performance') ORDER BY relevance_score DESC; +----+--------------------------------+-----------------+ | id | title | relevance_score | +----+--------------------------------+-----------------+ | 15 | MySQL Performance Tuning Guide | 3.45678 | | 23 | Optimizing MySQL Queries | 2.89123 | | 8 | Database Performance Tips | 1.23456 | +----+--------------------------------+-----------------+ العوامل المؤثرة على الصلة: - تكرار الكلمة في المستند (المزيد من الظهورات = درجة أعلى) - ندرة الكلمة عبر جميع المستندات (كلمات نادرة = درجة أعلى) - طول المستند (المستندات الأقصر تحصل على درجات أعلى) - موضع الكلمة (الكلمات في العنوان قد تحصل على درجة أعلى مع فهرس متعدد الأعمدة)
نصيحة: قم دائماً بتضمين درجة الصلة في SELECT الخاص بك لفهم لماذا يتم ترتيب النتائج بالطريقة التي هي عليها. هذا يساعدك على تحسين استعلامات البحث الخاصة بك.

الكلمات الإيقافية

الكلمات الإيقافية هي كلمات شائعة يتم تجاهلها من قبل البحث النصي الكامل:

الكلمات الإيقافية الافتراضية تشمل: a, an, and, are, as, at, be, by, for, from, in, is, it, of, on, or, that, the, this, to, was, will, with, ... -- هذه الاستعلامات متكافئة: MATCH(content) AGAINST('the database performance'); MATCH(content) AGAINST('database performance'); -- "the" يتم تجاهلها تلقائياً الحد الأدنى لطول الكلمة: - افتراضي: 4 أحرف (InnoDB)، 3 أحرف (MyISAM) - الكلمات الأقصر من الحد الأدنى يتم تجاهلها -- "SQL" (3 أحرف) قد يتم تجاهله مع إعدادات InnoDB الافتراضية MATCH(content) AGAINST('SQL database'); -- يبحث فقط عن "database"

تكوين الكلمات الإيقافية وطول الكلمة

-- عرض الإعدادات الحالية SHOW VARIABLES LIKE 'ft_%'; -- تغيير الحد الأدنى لطول الكلمة (يتطلب إعادة تشغيل الخادم) -- في my.cnf أو my.ini: [mysqld] innodb_ft_min_token_size = 3 -- الحد الأدنى لطول الكلمة لـ InnoDB ft_min_word_len = 3 -- الحد الأدنى لطول الكلمة لـ MyISAM -- استخدام قائمة كلمات إيقاف مخصصة innodb_ft_server_stopword_table = 'your_db/custom_stopwords'; -- بعد التغيير، أعد بناء فهارس FULLTEXT ALTER TABLE articles DROP INDEX ft_content; ALTER TABLE articles ADD FULLTEXT INDEX ft_content (content);

قيود البحث النصي الكامل

القيود التي يجب أن تكون على دراية بها: 1. فقط لأنواع أعمدة محددة: ✓ CHAR, VARCHAR, TEXT ✗ INT, DATE, BLOB 2. قيود محرك التخزين: ✓ InnoDB (MySQL 5.6+) ✓ MyISAM ✗ محركات Memory و CSV 3. غير حساس لحالة الأحرف: "MySQL" و "mysql" يُعاملان بنفس الطريقة 4. لا مطابقة سلسلة فرعية: "data" لن يطابق "database" (استخدم حرف بدل: data*) 5. قاعدة عتبة 50%: الكلمات التي تظهر في >50% من الصفوف يتم تجاهلها (أقل صلة بالوضع المنطقي) 6. الأداء على مجموعات بيانات كبيرة جداً: FULLTEXT سريع، لكن محركات البحث المخصصة (Elasticsearch) أفضل لملايين المستندات

حالات استخدام من العالم الحقيقي

مثال 1: بحث المدونة

-- مدونة مع عنوان ومقتطف ومحتوى CREATE TABLE blog_posts ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(255), excerpt TEXT, content TEXT, author VARCHAR(100), created_at TIMESTAMP, FULLTEXT KEY ft_title (title), FULLTEXT KEY ft_content (content), FULLTEXT KEY ft_all (title, excerpt, content) ); -- البحث في العناوين فقط (سريع، الأكثر صلة) SELECT * FROM blog_posts WHERE MATCH(title) AGAINST('MySQL performance'); -- البحث في جميع الحقول (شامل) SELECT id, title, MATCH(title, excerpt, content) AGAINST('MySQL performance') as score FROM blog_posts WHERE MATCH(title, excerpt, content) AGAINST('MySQL performance') ORDER BY score DESC LIMIT 10;

مثال 2: بحث المنتجات

CREATE TABLE products ( id INT PRIMARY KEY, name VARCHAR(255), description TEXT, category VARCHAR(50), price DECIMAL(10,2), FULLTEXT KEY ft_search (name, description) ); -- البحث عن المنتجات بالوضع المنطقي SELECT id, name, price, MATCH(name, description) AGAINST('+laptop +gaming -refurbished' IN BOOLEAN MODE) as relevance FROM products WHERE MATCH(name, description) AGAINST('+laptop +gaming -refurbished' IN BOOLEAN MODE) AND price BETWEEN 500 AND 2000 ORDER BY relevance DESC LIMIT 20; -- يجمع البحث النصي الكامل مع شروط WHERE العادية

مثال 3: قاعدة المعرفة

CREATE TABLE kb_articles ( id INT PRIMARY KEY, title VARCHAR(255), content TEXT, tags VARCHAR(255), views INT DEFAULT 0, FULLTEXT KEY ft_search (title, content, tags) ); -- بحث متقدم مع تعزيز الصلة SELECT id, title, views, MATCH(title, content, tags) AGAINST('+MySQL >performance >optimization' IN BOOLEAN MODE) as relevance FROM kb_articles WHERE MATCH(title, content, tags) AGAINST('+MySQL >performance >optimization' IN BOOLEAN MODE) ORDER BY relevance DESC, views DESC LIMIT 10; -- يرتب حسب الصلة أولاً، ثم حسب الشعبية (المشاهدات)

تمرين عملي:

السيناريو: تقوم ببناء موقع وصفات طعام مع بحث نصي كامل.

CREATE TABLE recipes ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(255), ingredients TEXT, instructions TEXT, cuisine VARCHAR(50), difficulty ENUM('easy', 'medium', 'hard'), prep_time INT, -- دقائق FULLTEXT KEY ft_search (title, ingredients, instructions) ); -- بيانات نموذجية INSERT INTO recipes (title, ingredients, instructions, cuisine, difficulty, prep_time) VALUES ('Classic Spaghetti Carbonara', 'pasta, eggs, bacon, parmesan, black pepper', 'Cook pasta. Fry bacon. Mix eggs and cheese. Combine all ingredients...', 'Italian', 'easy', 20), ('Chicken Tikka Masala', 'chicken, yogurt, tomato, cream, spices, garlic, ginger', 'Marinate chicken. Make sauce. Cook chicken in sauce...', 'Indian', 'medium', 45);

المهام:

  1. اكتب استعلاماً للعثور على وصفات تحتوي على "chicken" و "garlic"
  2. ابحث عن وصفات بـ "pasta" ولكن ليس "cream"
  3. ابحث عن وصفات بـ "spice" أو "spicy" (حرف بدل)
  4. ابحث عن وصفات "easy Italian" (اجمع البحث النصي الكامل مع WHERE العادي)

الحلول:

-- 1. يجب أن يحتوي على "chicken" و "garlic" SELECT title, cuisine, MATCH(title, ingredients, instructions) AGAINST('+chicken +garlic' IN BOOLEAN MODE) as score FROM recipes WHERE MATCH(title, ingredients, instructions) AGAINST('+chicken +garlic' IN BOOLEAN MODE) ORDER BY score DESC; -- 2. "pasta" ولكن ليس "cream" SELECT title, ingredients FROM recipes WHERE MATCH(title, ingredients, instructions) AGAINST('+pasta -cream' IN BOOLEAN MODE); -- 3. بحث حرف بدل عن spice/spicy SELECT title FROM recipes WHERE MATCH(title, ingredients, instructions) AGAINST('spic*' IN BOOLEAN MODE); -- 4. اجمع البحث النصي الكامل مع الشروط العادية SELECT title, cuisine, difficulty, prep_time FROM recipes WHERE MATCH(title, ingredients, instructions) AGAINST('Italian') AND difficulty = 'easy' AND prep_time <= 30 ORDER BY MATCH(title, ingredients, instructions) AGAINST('Italian') DESC;

الملخص

في هذا الدرس، تعلمت:

  • فهارس FULLTEXT تمكن البحث النصي السريع المرتب حسب الصلة
  • إنشاء فهارس FULLTEXT على أعمدة CHAR و VARCHAR و TEXT
  • وضع اللغة الطبيعية يبحث عن أي كلمات (افتراضي)
  • الوضع المنطقي يوفر تحكماً دقيقاً (+, -, *, "", عوامل)
  • توسيع الاستعلام يجد مصطلحات ذات صلة تلقائياً
  • درجات الصلة ترتب النتائج حسب جودة المطابقة
  • الكلمات الإيقافية والحد الأدنى لطول الكلمة تؤثر على سلوك البحث
  • البحث النصي الكامل أسرع بكثير من LIKE لعمليات البحث النصي
  • اجمع البحث النصي الكامل مع شروط WHERE العادية للاستعلامات القوية
التالي: في الدرس الأخير من هذه الوحدة، سنستكشف أفضل ممارسات الأداء بما في ذلك تجميع الاتصالات والعمليات الدفعية وتجنب مخاطر الأداء الشائعة!