حول المحتوى:
كيفية إنشاء محرك بحث سريع داخل التطبيقات باستخدام Elasticsearch مع أمثلة للفهرسة والاستعلام.
محرك البحث الداخلي أصبح جزءًا أساسيًا من أي تطبيق حديث، سواء كان موقع تجارة إلكترونية، منصة محتوى، أو نظام إدارة بيانات. الاعتماد فقط على استعلامات SQL التقليدية لا يكون كافيًا عند الحاجة إلى بحث نصي سريع، مرن، وذكي. هنا يأتي دور Elasticsearch Search Engine كأحد أقوى الحلول المفتوحة المصدر لبناء محركات بحث متقدمة داخل التطبيقات.
في هذا المقال على افهم صح سنشرح بشكل مبسط كيف تبني محرك بحث داخلي باستخدام Elasticsearch، بداية من المفاهيم الأساسية، ثم إعداد الفهرسة (Indexing)، وحتى تنفيذ الاستعلامات (Queries) مع أمثلة عملية يمكن دمجها مع أي Backend مثل Django أو FastAPI.
Elasticsearch هو محرك بحث وتحليل موزّع مبني على مكتبة Lucene. تم تصميمه للتعامل مع كميات ضخمة من البيانات النصية والرقمية، مع توفير:
على عكس قواعد البيانات العلائقية التقليدية، Elasticsearch مُصمم خصيصًا لعمليات البحث المعقدة، مثل البحث بالتقريب، التصحيح الإملائي، واقتراح النتائج، وهو ما يجعله خيارًا مثاليًا لبناء محرك بحث داخلي في تطبيقك.
للتعامل مع Elasticsearch Search Engine بفعالية، من المهم فهم نموذج البيانات الخاص به:
معرفة هذه المفاهيم تشبه فهم كيفية عمل الفهارس في قواعد البيانات التقليدية، والتي تحدثنا عنها في مقال أهم خوارزميات الفهرسة المستخدمة في قواعد البيانات، لكن Elasticsearch يستخدم أسلوبًا متقدمًا ومخصصًا أكثر للبحث النصي.
لجعل الشرح عمليًا، سنفترض وجود تطبيق تجارة إلكترونية نريد فيه:
سنستخدم Elasticsearch كخدمة بحث موازية لقاعدة البيانات الأساسية (مثل PostgreSQL أو MySQL)، بحيث يتم تخزين البيانات الأساسية في قاعدة البيانات، بينما يتم إرسال نسخة إلى Elasticsearch للفهرسة والبحث.
أسهل طريقة للتجربة هي استخدام Docker:
docker run -d --name es \
-p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
docker.elastic.co/elasticsearch/elasticsearch:8.12.0
بعد تشغيله، يمكنك التأكد من أنه يعمل عبر طلب HTTP بسيط:
curl http://localhost:9200 للفهرسة الجيدة، يجب تعريف Mapping يلائم طبيعة البيانات التي نبحث فيها. مثال لفهرس products:
curl -X PUT "http://localhost:9200/products" \
-H "Content-Type: application/json" \
-d '{
"mappings": {
"properties": {
"name": {
"type": "text",
"analyzer": "standard"
},
"description": {
"type": "text",
"analyzer": "standard"
},
"category": {
"type": "keyword"
},
"price": {
"type": "float"
},
"created_at": {
"type": "date"
}
}
}
}'
ملاحظات سريعة:
الخطوة التالية هي إرسال بيانات المنتجات إلى الفهرس. يمكن أن يتم ذلك من خلال:
مثال بسيط لإضافة منتج واحد:
curl -X POST "http://localhost:9200/products/_doc/1" \
-H "Content-Type: application/json" \
-d '{
"name": "هاتف ذكي سامسونج جالاكسي",
"description": "هاتف ذكي بشاشة 6.5 بوصة وذاكرة 128 جيجابايت",
"category": "smartphones",
"price": 2500.0,
"created_at": "2024-03-01T10:00:00"
}'
يمكنك أيضًا استخدام Bulk API لفهرسة عدد كبير من المنتجات في طلب واحد، وهو مفيد جدًا عند تهيئة النظام لأول مرة.
باستخدام multi_match للبحث في أكثر من حقل:
curl -X GET "http://localhost:9200/products/_search" \
-H "Content-Type: application/json" \
-d '{
"query": {
"multi_match": {
"query": "هاتف ذكي",
"fields": ["name", "description"]
}
}
}'
هذا الاستعلام سيعيد المنتجات التي تحتوي عبارات قريبة من "هاتف ذكي" في الاسم أو الوصف، مع ترتيبها حسب الصلة (Relevance Score).
هنا نستخدم bool مع must و filter:
curl -X GET "http://localhost:9200/products/_search" \
-H "Content-Type: application/json" \
-d '{
"query": {
"bool": {
"must": {
"multi_match": {
"query": "هاتف",
"fields": ["name", "description"]
}
},
"filter": [
{ "term": { "category": "smartphones" } },
{ "range": { "price": { "gte": 2000, "lte": 3000 } } }
]
}
},
"sort": [
{ "price": "asc" }
]
}'
بهذا الشكل يمكن للمستخدم البحث عن "هاتف" مع حصر النتائج في تصنيف الهواتف الذكية، وبسعر بين 2000 و 3000، والنتائج مرتبة من الأرخص إلى الأغلى.
من الميزات المفيدة في محركات البحث الداخلية هي مساعدة المستخدم عند وجود أخطاء إملائية أو تقديم اقتراحات. مثال باستخدام term suggester:
curl -X GET "http://localhost:9200/products/_search" \
-H "Content-Type: application/json" \
-d '{
"query": {
"match": {
"name": "هتف ذكي"
}
},
"suggest": {
"name_suggest": {
"text": "هتف ذكي",
"term": {
"field": "name"
}
}
}
}'
Elasticsearch سيحاول اقتراح تصحيحات لعبارة "هتف" إلى "هاتف" مثلاً، ويمكنك عرض هذه الاقتراحات في واجهة المستخدم.
أفضل طريقة للاستفادة من Elasticsearch هي دمجه مع واجهة برمجية RESTful API، مثل ما شرحناه في مقال بناء RESTful APIs باستخدام FastAPI. الفكرة العامة:
مثال باستخدام مكتبة elasticsearch في بايثون:
from elasticsearch import Elasticsearch
es = Elasticsearch("http://localhost:9200")
def index_product(product_id, name, description, category, price, created_at):
doc = {
"name": name,
"description": description,
"category": category,
"price": price,
"created_at": created_at
}
es.index(index="products", id=product_id, document=doc)
def search_products(query, category=None, price_min=None, price_max=None):
must_clauses = [
{
"multi_match": {
"query": query,
"fields": ["name", "description"]
}
}
]
filters = []
if category:
filters.append({"term": {"category": category}})
if price_min is not None or price_max is not None:
price_range = {}
if price_min is not None:
price_range["gte"] = price_min
if price_max is not None:
price_range["lte"] = price_max
filters.append({"range": {"price": price_range}})
body = {
"query": {
"bool": {
"must": must_clauses,
"filter": filters
}
}
}
result = es.search(index="products", body=body)
return result["hits"]["hits"]
هذا الكود يمكن لفريمورك مثل Django أو FastAPI أن يلتف حوله في Endpoint واحد للبحث، بحيث يتم استدعاؤه من واجهة المستخدم (Front-end).
يمكنك الاطلاع على كيفية استخدام Redis لتخفيف الحمل وتحسين الأداء في مقال Redis كمخزن مؤقت للتطبيقات، حيث يمكن ربطه أيضًا بمنظومة البحث لتسريع الاستعلامات المتكررة.
_source لتحديد الحقول المطلوبة فقط.from و size أو عبر search_after للبيانات الكبيرة. يمكن لقواعد البيانات العلائقية تقديم بحث بسيط باستخدام LIKE أو فهارس نصية، لكن عندما تحتاج إلى:
يصبح استخدام Elasticsearch Search Engine أو مشابهاته (مثل Solr) هو الحل الأنسب. قاعدة البيانات تظل مسؤولة عن المعاملات (Transactions) وسلامة البيانات، بينما Elasticsearch يقدم طبقة بحث وتحليل مخصصة.
بناء محرك بحث داخلي قوي داخل التطبيقات لم يعد رفاهية، بل جزء أساسي من تجربة المستخدم. استخدام Elasticsearch Search Engine يمنحك:
من خلال فهم بنية Elasticsearch، وإنشاء الفهارس بشكل صحيح، وتصميم استعلامات مرنة، يمكنك بناء نظام بحث داخلي احترافي لتطبيقك، سواء كان موقع محتوى، متجر إلكتروني، أو منصة بيانات متقدمة. ومع الربط الجيد مع Backend Frameworks مثل Django و FastAPI، ستحصل على بنية بحث قابلة للتوسع وسهلة الصيانة.
إذا كنت مهتمًا أكثر بكيفية تنظيم طبقة البيانات في مشاريع بايثون، يمكنك أيضًا مراجعة دليل استخدام Django ORM لتفهم كيف تُدار البيانات في طبقة التطبيق جنبًا إلى جنب مع طبقة البحث باستخدام Elasticsearch.
كيفية إنشاء محرك بحث سريع داخل التطبيقات باستخدام Elasticsearch مع أمثلة للفهرسة والاستعلام.
مساحة اعلانية