البحث المتجه الدلالي ومواضيع أخرى لكسب الأصدقاء والعشاق
المشهد الكامل للبحث: الدقة، التقريب، الدلالية، والهجين — ومتى ندمجهم جميعًا.
البحث ليس شيئًا واحدًا، والبحث الدلالي ليس بديلاً لبقية الأنواع.
“العثور على مستخدم بالبريد الإلكتروني dan@example.com” و”ابحث لي عن مقالات حول تصحيح الأخطاء كمطور جديد” يُوصفان كلاهما بالبحث، لكنهما لا يشتركان تقريبًا في أي شيء كمشكلة هندسية. الأول له إجابة صحيحة ويتطلب عملية بحث في الفهرس بـ O(log n). الثاني لا يمتلك إجابة صحيحة — فقط صلة — ويتطلب فهم اللغة والنية والمعنى.
المهندسون الذين يملكون أقوى الحُجج حول قرارات البحث — الذين يفوزون بالجدال ويطلقون النظام الصحيح — هم الذين يدركون المشهد بالكامل. يعرفون أي أداة يجب أن يستخدموها ولماذا، ويمكنهم شرح ذلك بوضوح.
هذه المقالة تغطي الطبقة الدلالية: ما الذي يفعله بحث المتجهات فعليًا، ومتى ينجح، وأين يجب أن يبقى بعيدًا عن الطريق. النسخة المفيدة ليست “تضمين كل شيء”. إنها معرفة متى يجب أن تكون المتجهات بجانب البحث المعجمي، الضبابي، والبحث بالتطابق الدقيق في بنية هجينة.
النصف المعجمي والضبابي من الصورة — tsvector، pg_trgm، pg_search — موجود في دليل بحث النص في PostgreSQL 2026.
المصطلحات لمحة سريعة
Embedding — قائمة كثيفة من الأعداد العائمة التي ينتجها نموذج، تمثل قطعة نصية (أو صورة، صوت، إلخ) كنقطة في فضاء عالي الأبعاد. المحتوى المتعلق دلاليًا يقترب؛ المحتوى غير المتعلق يبتعد.
Lexical search — بحث يعتمد على مطابقة الكلمات والرموز الدقيقة. سريع، حتمي، وصحيح للمصطلحات المعروفة. لا يفهم المرادفات أو الصياغات البديلة أو المكافئات عبر اللغات.
Semantic search — بحث يعتمد على المعنى بدلاً من الرموز. يمكن لاستعلام مثل “كيف أتعامل مع مهلات الوقت” أن يطابق مستندًا بعنوان “تكوين سياسات إعادة المحاولة” دون أي كلمات مشتركة، لأن تمثيلاتهما المتجهية قريبة هندسيًا.
المتجه — قائمة من الأرقام. في سياق البحث، هو ناتج نموذج التضمين. «بحث المتجهات» يجد المتجهات الأقرب إلى متجه الاستعلام عبر المسافة الهندسية.
بحث النص الكامل (FTS) — البحث اللغوي المدمج في PostgreSQL، المدعوم بـ tsvector / tsquery. يقوم بتقسيم النص إلى رموز، وتطبيق الجذور، وفهرسة النص لاستعلامات الكلمات المفتاحية. قوي للنصوص النثرية والبحث عن المصطلحات الدقيقة؛ لكنه أعمى عن المعنى.
BM25 — خوارزمية ترتيب للبحث اللغوي (تُستخدم في Elasticsearch، Qdrant، وغيرها). تُحسب الدرجات بناءً على تكرار المصطلح مع وزن ندرته عبر المجموعة. أفضل من المطابقة البسيطة للكلمات المفتاحية؛ لكنه يظل لغويًا.
HNSW (Hierarchical Navigable Small World) — الفهرس التقريبي القياسي لأقرب الجيران في بحث المتجهات. يبني رسمًا بيانيًا متعدد الطبقات للقرابة لتوفير استعلامات تشابه سريعة وعالية الاستدعاء. يستخدمه pgvector، Qdrant، Weaviate، ومعظم الأنظمة الأخرى.
RRF (Reciprocal Rank Fusion) — خوارزمية لدمج قوائم النتائج المرتبة من أنظمة استرجاع متعددة. تعتمد فقط على موضع الترتيب — لا تحتاج إلى تطبيع الدرجات. النتيجة التي تحتل مرتبة عالية في كل من قوائم FTS والمتجه تحصل على درجة مركبة أقوى من تلك التي تتفوق في واحدة فقط.
ما يفعله البحث الدلالي فعليًا
تحويلات المتجهات تُحوِّل النص (أو الصور، الصوت، إلخ) إلى قائمة من الأرقام — نقطة في فضاء عالي الأبعاد. يتم تدريب نموذج التضمين بحيث تكون النصوص ذات الصلة الدلالية قريبة من بعضها في ذلك الفضاء. «Dog» و«canine» يقتربان. «Running a marathon» و«running a Python script» يبتعدان رغم اشتراكهما في كلمة «running».
بحث التشابه في ذلك الفضاء يجد المستندات التي معناها أقرب إلى معنى الاستعلام، بغض النظر عن تداخل الكلمات الدقيقة.
هذا يعني:
- يمكن لاستعلام «How do I configure request timeouts?» أن يطابق مقالة بعنوان «Setting connection limits and retry policies» — لا توجد كلمات مفتاحية مشتركة، لكن الصلة المفهومية عالية
- يمكن لاستعلام «Something light for a summer evening» أن يطابق توصية نبيذ دون أي كلمة مفتاحية تظهر في وصف المنتج
- يمكن لاستعلام بالإنجليزية أن يطابق مستندات ذات صلة بالفرنسية أو الإسبانية أو اليابانية إذا كان نموذج التضمين مدربًا متعدد اللغات
البحث المعجمي (tsvector، pg_trgm) لا يستطيع فعل أي من ذلك. فهو يعمل على الكلمات والحروف، وليس على المعنى. الأدوات ليست قابلة للاستبدال — كل منها يحل مشكلة مختلفة.
متى يتفوق pgvector
بناء RAG. الاسترجاع المعزز للتوليد (Retrieval‑Augmented Generation) يجلب أجزاء المستند التي يكون معناها أقرب إلى سؤال المستخدم، ثم يمررها إلى نموذج اللغة كسياق. خطوة الاسترجاع هذه هي عملية متجهية. البحث النصي الكامل سيفوت الصيغ المعادلة، المرادفات، والتطابقات المفاهيمية التي قد يعبر عنها الجزء ذي الصلة بطريقة مختلفة. ميزة pgvector مقارنةً بمخزن متجهات مستقل هي أنه يعمل داخل قاعدة PostgreSQL الحالية — لا حاجة لخدمة منفصلة للنشر، التشغيل، أو مزامنة البيانات.
المستخدمون يصفون ما يريدون، لا ما يجب البحث عنه. “مقالات عن بناء الثقة كمدير جديد” لا تحتوي على كلمات مفتاحية تظهر بانتظام في المشاركات ذات الصلة. “إطار عمل خفيف لمعالجة الآثار الجانبية” قد لا يستخدم تلك الكلمات الدقيقة في الوثائق. البحث المتجهي يطابق النية، لا الإملاء.
العثور على عناصر مشابهة. منتجات مرتبطة، تذاكر دعم مشابهة، تقارير أخطاء مكررة، مقالات قد تعجبك أيضاً. “ابحث عن مشاكل مشابهة لهذه” هو بحث أقرب جارٍ — يتم تضمين العنصر، ثم العثور على جيرانه الهندسيين. تحذير مهم: البحث المتجهي يعيد دائماً نتائج، حتى عندما لا يكون هناك تشابه حقيقي. لحالات إزالة التكرار والتوصية، يجب تصفية النتائج بحد أدنى للتشابه (مثلاً، تشابه جيبي ≥ 0.80) لتجنب إظهار تطابقات منخفضة الثقة كأنها ذات معنى.
إزالة التكرار الدلالي. قبل فهرسة المحتوى لـ RAG أو البحث، غالباً ما تحتاج إلى تحديد النسخ القريبة في المجموعة — مقالات تم تعديلها عدة مرات، تذاكر دعم مكررة، مدخلات قاعدة معرفة تتقاطع بشكل كبير. قم بتضمين المستندات ثم صفيها بحد تشابه جيبي لتعليم أو دمج النسخ القريبة قبل أن تلوث الفهرس. هذا يمنع الاسترجاع من إرجاع عدة أجزاء شبه متطابقة ويقلل من تشتت نافذة السياق.
البحث متعدد اللغات. نماذج التضمين متعددة اللغات تُطابق المحتوى الدلالي المكافئ عبر اللغات إلى متجهات قريبة. استعلام بالإسبانية عن “perder peso” يمكن أن يطابق مقالة إنجليزية حول “عادات فقدان الوزن المستدامة” — لا توجد رموز مشتركة، لكن المعنى الأساسي هو نفسه. البحث النصي الكامل يتطلب إعداد قواميس لكل لغة ويتعامل مع الاستعلامات عبر اللغات بشكل ضعيف. pg_trgm لا يهمه اللغة لكنه يعتمد على الشكل الكتابي، وليس الدلالي.
إعداد pgvector
من تثبيت الامتداد إلى استعلام التشابه، الإعداد يتكون من بضع جمل SQL فقط:
CREATE EXTENSION IF NOT EXISTS vector;
ALTER TABLE documents ADD COLUMN embedding vector(1536);
-- HNSW هو عادة الفهرس الأول الذي نجربه لمجموعات البيانات المتوسطة الحجمCREATE INDEX documents_embedding_idx ON documents USING hnsw (embedding vector_cosine_ops);
-- استعلام البحث الدلاليSELECT id, title, 1 - (embedding <=> $1::vector) AS similarityFROM documentsORDER BY embedding <=> $1::vectorLIMIT 10;<=> هو مسافة جيبية. 1 - cosine_distance يعطي تشابه جيبي (1.0 = متطابق تمامًا، 0.0 = عمودي). بالنسبة إلى ivfflat (البديل الأقدم الأسرع في الإنشاء)، استخدم lists = sqrt(row_count) كنقطة انطلاق.
ما لا يتقنه pgvector جيدًا
- المطابقة الدقيقة للرموز — رموز المنتجات، رموز الأخطاء، أسماء الدوال.
ORD-12345ليس له تشابه دلالي مع أي شيء. بحث يعتمد على التضمين قد يُرجعORD-12344أو لا يُرجع شيء ذي صلة. استخدم FTS أو فهرس B‑tree. - الأسماء والأسماء الخاصة. فضاء التضمين يُنظم حسب المعنى، وليس حسب التهجئة. سجل المستخدم “Micheal Jordan” قد لا يقع بالقرب من “Michael Jordan” في فضاء المتجهات.
- السلاسل القصيرة التي تكون فيها التشابه على مستوى الأحرف أهم من المعنى.
pg_trgmيتعامل مع هذا. - الاستعلامات التي يجب أن يظهر فيها المصطلح الدقيق. BM25 و FTS أكثر موثوقية للمطابقة المعروفة للمصطلحات.
البحث الهجين: الحالة التي تحتاج كلاهما
توثيق التقنية هو المثال الأكثر وضوحًا حيث لا يكفي أي من الأداتين بمفردهما.
المستخدمون الذين يبحثون عن “how to configure timeouts” يحتاجون إلى مطابقة مفهومية: مقالة بعنوان “Setting retry policies and connection limits” لا تشترك في أي كلمة مفتاحية لكنها بالضبط ما يحتاجونه.
نفس المستخدمين يبحثون أيضًا عن withRetry(), ECONNRESET, و ERR_SOCKET_TIMEOUT. يجب أن تظهر هذه السلاسل الدقيقة — المطابقة الدلالية قد لا تجدها بموثوقية، وإيجاد إيجابي زائف (مفهومي مشابه لكنه ليس الـ API الصحيح) يكون مضللًا فعليًا.
البحث الدلالي يتعامل مع الاستعلامات المفهومية. FTS يتعامل مع المصطلحات الدقيقة. لا أحد منهما يتقن كليهما بمفرده.
الحل هو البحث الهجين: تشغيل كلاهما ودمج النتائج.
دمج الرتبة العكسية
دمج الرتبة العكسية (RRF) هو الخوارزمية القياسية لدمج القوائم المرتبة من أنظمة استرجاع مختلفة. لا يتطلب تطبيع الدرجات بين الأنظمة — فهو يستخدم فقط مواضع الرتبة. النتيجة التي تظهر مرتبة عالية في كلا القائمتين تحصل على درجة مركبة أقوى من تلك التي تتفوق فقط في واحدة.
WITH fts_results AS ( SELECT id, ROW_NUMBER() OVER (ORDER BY ts_rank(search_vector, query) DESC) AS rank FROM documents, to_tsquery('english', $1) query WHERE search_vector @@ query LIMIT 50),vector_results AS ( SELECT id, ROW_NUMBER() OVER (ORDER BY embedding <=> $2::vector) AS rank FROM documents ORDER BY embedding <=> $2::vector LIMIT 50),rrf AS ( SELECT COALESCE(f.id, v.id) AS id, COALESCE(1.0 / (60 + f.rank), 0) + COALESCE(1.0 / (60 + v.rank), 0) AS rrf_score FROM fts_results f FULL OUTER JOIN vector_results v ON f.id = v.id)SELECT d.id, d.title, rrf.rrf_scoreFROM rrfJOIN documents d ON d.id = rrf.idORDER BY rrf_score DESCLIMIT 10;العدد 60 في المقام هو ثابت RRF. القيم الأعلى تخفّف من الفروقات بين مواضع الرتبة؛ القيم الأقل تضخمها. القيمة الافتراضية 60 تعمل جيدًا لمعظم أنواع المحتوى.
يتجنّب RRF مشكلة تطبيع ts_rank (درجة تعتمد على تردد اللوغاريتم) مقابل مسافة جيبية (مقياس هندسي). لا يمكن مقارنتهما. يقتصر RRF على سؤال واحد: “ما مدى ارتفاع ظهور هذه النتيجة في كل قائمة؟“
البحث الهجين مع الـ Trigrams أيضًا
للبحث الموجه للمستخدم على محتوى مختلط — حيث قد يبحث المستخدم عن اسم شخص، مفهوم، أو مصطلح دقيق في نفس الجلسة — يتيح الدمج الثلاثي التعامل مع جميع الحالات:
WITH trgm_results AS ( SELECT id, ROW_NUMBER() OVER (ORDER BY similarity(title, $1) DESC) AS rank FROM documents WHERE title % $1 LIMIT 50),fts_results AS ( SELECT id, ROW_NUMBER() OVER (ORDER BY ts_rank(search_vector, to_tsquery('english', $1)) DESC) AS rank FROM documents WHERE search_vector @@ to_tsquery('english', $1) LIMIT 50),vector_results AS ( SELECT id, ROW_NUMBER() OVER (ORDER BY embedding <=> $2::vector) AS rank FROM documents ORDER BY embedding <=> $2::vector LIMIT 50),rrf AS ( SELECT COALESCE(t.id, f.id, v.id) AS id, COALESCE(1.0 / (60 + t.rank), 0) + COALESCE(1.0 / (60 + f.rank), 0) + COALESCE(1.0 / (60 + v.rank), 0) AS rrf_score FROM trgm_results t FULL OUTER JOIN fts_results f ON t.id = f.id FULL OUTER JOIN vector_results v ON COALESCE(t.id, f.id) = v.id)SELECT d.id, d.title, rrf.rrf_scoreFROM rrfJOIN documents d ON d.id = rrf.idORDER BY rrf_score DESCLIMIT 10;هذا يعالج: مطابقة الأسماء غير الدقيقة (trigrams)، مطابقة الكلمات المفتاحية الدقيقة (FTS)، والاستعلامات المفهومية (vector). يمكن لصندوق بحث واحد أن يخدم جميع نوايا المستخدم الثلاث.
بنى هجينة متعددة الطبقات
التطبيقات الواقعية نادراً ما تقتصر على سطح بحث واحد. لديها عدة أسطح، كل منها يحتاج إلى نهج مختلف:
| Surface | ما الذي يستعلم عنه المستخدمون | الطبقات الموصى بها |
|---|---|---|
| بحث في المدونات / الوثائق | كلمات مفتاحية + مفاهيم | FTS + pgvector (RRF) |
| البحث عن اسم المستخدم / العميل | أسماء مع أخطاء إملائية | pg_trgm |
| بحث عن منتجات | أسماء، أوصاف، “مشابه لـ” | pg_trgm + FTS + pgvector |
| كشف التكرار في تذاكر الدعم | “مشكلات مشابهة لهذه” | pgvector فقط |
| بحث داخلي عن SKU / طلبات | معرفات دقيقة | فهرس B‑tree |
| RAG على قاعدة معرفة ضخمة | أسئلة بلغة طبيعية | pgvector (مستندات مقطعة) |
| “قد يعجبك أيضاً” في التجارة الإلكترونية | تشابه سلوكي + دلالي | pgvector |
| الإكمال التلقائي | بادئة، تحمل تسامحاً مع الأخطاء الإملائية | pg_trgm |
هذه ليست سيناريوهات افتراضية. معظم التطبيقات التي تتعامل مع محتوى كثيف تحتاج على الأقل إلى سطحين بحثيين مميزين بأشكال استعلام مختلفة. الإغراء يكون غالباً باختيار نهج واحد واستخدامه في كل مكان — عادةً البحث المتجهي الآن، لأنه الخيار الشائع. هذا يؤدي إلى توليد embeddings مكلفة لمشكلات كان من الممكن حلها بفهرس trigram أسرع، أرخص، وأكثر دقة.
قاعدة الإبهام
أضف طبقة عندما تظهر حالة فشل لا تستطيع الطبقة الحالية معالجتها:
- يشتكي المستخدمون من عدم مطابقة الأخطاء الإملائية → أضف
pg_trgm - يبحث المستخدمون بالمفهوم ويفوتهم النتائج ذات الصلة → أضف pgvector
- يبحث المستخدمون عن رموز أو أكواد دقيقة ويحصلون على نتائج مفهومية بدلاً من ذلك → أضف FTS أو تحقق مما إذا كنت تعتمد بشكل مفرط على البحث المتجهي
- تصبح الكمون مشكلة → قيم ما قبل الترشيح، الفهارس التقريبية، أو مخزن مخصص
إذا كنت بحاجة إلى مخزن متجهي مخصص
pgvector يتعامل مع معظم عمليات البحث في التطبيقات قبل أن تحتاج إلى قاعدة بيانات أخرى. الحد التقريبي يعتمد على عدد المتجهات، إعدادات الفهرس، معدل الكتابة، الفلاتر، العتاد، والتزامن، لذا اعتبر أي قاعدة “أقل من 10 ملايين متجه” مجرد افتراض مبدئي للقياس، وليس حدًا للمنتج. عندما تتجاوز ذلك فعليًا — تزامن عالي جداً، متطلبات زمن استجابة p99 منخفضة جداً، مليارات المتجهات، أو حاجة حقيقية لعزل متعدد المستأجرين — يصبح مشهد قواعد البيانات المتجهية المخصصة واسعًا ويستحق الفهم.
ما تعنيه أعمدة المصفوفة فعليًا
البحث الهجين يعني تشغيل بحث BM25 بالكلمات المفتاحية والبحث المتجهي في استعلام واحد، ثم دمجهما عبر RRF. بدون ذلك، إما تختار وضع بحث واحد أو تقوم بدمج استعلامين بنفسك.
المتجهات المتناثرة تتجاوز BM25. متجه SPLADE المتناثر يحتوي على ~30,000 بُعد (واحد لكل مصطلح في المفردات)، ~98 % أصفار. المواقع غير الصفرية تخبرك أي المصطلحات مهمة وكم مقدارها. استعلام “dogs” يوزن أيضاً “canine” و“pet” — دقة مستوى BM25 مع توسيع المصطلحات داخل فهرس المتجهات. إذا كان هذا العمود غير مفعّل، تحتاج طبقة FTS منفصلة لاستعلامات المصطلحات الدقيقة.
# SPLADE: ~30,000 dims, ~60 non-zero — only relevant vocabulary positions firedef encode_splade(text: str) -> dict: tokens = tokenizer(text, return_tensors="pt", truncation=True, max_length=512) with torch.no_grad(): output = model(**tokens) vec = torch.log1p(torch.relu(output.logits)).max(dim=1).values.squeeze() return {"indices": vec.nonzero().squeeze().tolist(), "values": vec[vec != 0].tolist()}SQL / شبيهة‑SQL هي في الأساس عن الترشيح. البحث المتجهي بدون ترشيح هو مجرد عرض توضيحي. لا يزال عليك تطبيق نطاق المستأجر، نطاقات التاريخ، الأذونات، ومرشحات الفئات. SQL الكامل (pgvector، LanceDB) يعبر عن ذلك إلى جانب عمليات الانضمام الحالية. قواعد البيانات المصممة خصيصاً تستخدم كائنات ترشيح JSON (Qdrant، Pinecone)، لغة استعلام DSL (Elasticsearch، Milvus)، أو GraphQL (Weaviate). كلها تعمل؛ يصبح SQL أكثر جاذبية مع تعقيد منطق الترشيح.
-- pgvector: vector similarity is just another expressionSELECT id, title, 1 - (embedding <=> $1) AS scoreFROM documentsWHERE tenant_id = $2 AND category = ANY($3::text[]) AND created_at > NOW() - INTERVAL '90 days'ORDER BY embedding <=> $1LIMIT 10;# Qdrant: equivalent filter as a Python object — same result, more ceremonyresults = client.query_points( collection_name="documents", query=query_embedding, query_filter=models.Filter(must=[ models.FieldCondition(key="tenant_id", match=models.MatchValue(value=tenant_id)), models.FieldCondition(key="category", match=models.MatchAny(any=categories)), models.FieldCondition(key="created_at", range=models.DatetimeRange(gte=cutoff)), ]), limit=10,)الطبيعي المتعدد الوسائط يعني أن قاعدة البيانات تُرفق نماذج تضمين للمحتوى غير النصي. تعطيها عنوان صورة خام؛ تتولى تحويلها إلى متجه. معظم القواعد غير مرتبطة بالتضمين — أنت تدير خط أنابيب التضمين. Marqo وWeaviate (عبر وحدات CLIP/ImageBind) يغلقان هذه الحلقة.
# Marqo: POST raw images, query with text — no external embedding stepmq.index("products").add_documents( [{"id": "shoe-001", "image": "https://cdn.example.com/shoes/001.jpg"}], tensor_fields=["image"])results = mq.index("products").search(q="lightweight shoes for summer")# Returns shoe-001 despite zero keyword overlap — CLIP handles the cross-modal matchالفهرس القائم على القرص هو رافعة تكلفة. فهارس HNSW المقيمة في الذاكرة قد تتطلب عدة جيجابايت من RAM لكل مليون متجه بأبعاد 1536 عندما تُحسب المتجهات الخام، وإجهاد الرسم البياني، والبيانات الوصفية. البدائل القابلة للتخزين على القرص (Milvus DiskANN، Elasticsearch DiskBBQ، صيغة Lance في LanceDB، طبقة التخزين الكائني في Turbopuffer) غالباً ما تُقايض بعض زمن الاستجابة مقابل خفض تكلفة البنية التحتية. لأعباء عمل RAG حيث يهيمن زمن استجابة النموذج بالفعل، غالباً ما يكون هذا القيد جديراً بالاختبار.
الحد الأقصى للأبعاد هو ترحيل مخفي في بنية النظام. text-embedding-3-large يستخدم 3072 بُعد، Jina v3 يمكنه إنتاج تضمينات أكبر، والنماذج البحثية تستمر في دفع الأبعاد أعلى. بعض الخدمات المدارة تنشر حدود أبعاد صريحة؛ أخرى توثق حدوداً عالية أو لا تضع حدًا عمليًا للنماذج الشائعة. تحقق من الوثائق الحالية قبل الالتزام. اختر ما يترك مساحة للنمو؛ ترحيل فهرس متجه لأنك صادفت سقف أبعاد هو سباق مرهق.
تم التحقق من صحة المعلومات مقابل وثائق المشاريع العامة وصفحات المنتجات في 8 مايو 2026. اعتبر الجدول أدناه أداة مساعدة في اتخاذ القرار، وليس بديلاً عن مراجعة الحدود الحالية، التسعير، وعلمات ميزات الخدمات المدارة.
المشهد العام
| قاعدة البيانات | النشر | الترخيص | البحث الهجين | المتجهات المتناثرة | SQL / شبيهة‑SQL | متعدد الوسائط | فهرس على قرص | الحد الأقصى للأبعاد | النقطة المثالية |
|---|---|---|---|---|---|---|---|---|---|
| pgvector | استضافة ذاتية / مُدارة (Supabase, Neon, RDS) | OSS (PostgreSQL) | يدوي (RRF عبر SQL) | ❌ | ✅ SQL كامل | ❌ | ✅ HNSW على قرص | 16,000 تخزين؛ 2,000 مفهرسة vector | موجود بالفعل على Postgres؛ عدد متجهات متوسط |
| Qdrant | استضافة ذاتية / سحابة | Apache 2.0 | ✅ BM25 أصلي | ✅ دعم ناضج | ❌ (REST/gRPC) | ❌ | ✅ | 65,535 | استعلامات مُرشحة على نطاق واسع؛ بيانات وصفية معقّدة |
| Weaviate | استضافة ذاتية / سحابة | BSD 3 | ✅ BM25 أصلي + RRF | ✅ | ❌ (GraphQL / gRPC) | ✅ عبر الوحدات | ✅ | 65,535 | أنماط وصول GraphQL؛ تضمين مدمج |
| Pinecone | سحابة فقط | Proprietary | ✅ (أضيف 2024) | ✅ | ❌ | ❌ | ✅ (بدون خادم) | 20,000 | بساطة مُدارة؛ لا فريق عمليات |
| Milvus / Zilliz | استضافة ذاتية / سحابة (Zilliz) | Apache 2.0 | ✅ أصلي | ✅ | ✅ شبيهة‑SQL (Milvus Query Language) | ✅ | ✅ DiskANN | 32,768 | مقياس بمليارات؛ مؤسسات داخلية |
| Chroma | مدمج / استضافة ذاتية | Apache 2.0 | ❌ | ❌ | ❌ | ❌ | ❌ | 65,535 | تطوير محلي ونمذجة أولية فقط |
| LanceDB | مدمج / سحابة | Apache 2.0 | ✅ | ❌ | ✅ SQL عبر DataFusion | ✅ أصلي | ✅ (صيغة Lance) | غير محدود | حافة / بدون خادم؛ بحيرة بيانات متعددة الوسائط |
| Orama | مدمج / سحابة | Apache 2.0 | ✅ نص كامل + متجه | ❌ | ❌ | ❌ | ❌ | متنوع | تطبيقات JS/edge؛ بحث خفيف للمواقع |
| Turbopuffer | سحابة فقط (بدون خادم) | Proprietary | ✅ BM25 + متجه | ❌ | ❌ | ❌ | ✅ (تخزين كائنات) | 16,000 | SaaS متعدد المستأجرين؛ ملايين المساحات الاسمية |
| Elasticsearch | استضافة ذاتية / Elastic Cloud | SSPL / AGPLv3 | ✅ RRF + ELSER متناثر | ✅ (ELSER) | ✅ DSL الاستعلام | ❌ | ✅ DiskBBQ | 4,096 | موجود بالفعل في مجموعة Elastic؛ بحث مؤسسي هجين |
| OpenSearch | استضافة ذاتية / مُدارة AWS | Apache 2.0 | ✅ RRF + بحث عصبي | ✅ | ✅ DSL الاستعلام | ❌ | ✅ FAISS + HNSW | 16,000 | أصلي لـ AWS؛ بديل مفتوح المصدر لـ Elastic |
| Vespa | استضافة ذاتية / سحابة | Apache 2.0 | ✅ أصلي | ✅ موترات / ترتيب لغوي | ✅ YQL | ✅ موترات | ✅ | غير محدود عمليًا | بحث + ترتيب + توصية |
| ClickHouse | استضافة ذاتية / سحابة | Apache 2.0 | يدوي | ❌ | ✅ SQL كامل | ❌ | ✅ عمودي + HNSW | متنوع | تحليلات/سجلات مع بحث متجه إلى جانب OLAP |
| MongoDB Atlas | سحابة / استضافة ذاتية | SSPL | ✅ مدمج | ❌ | ✅ MQL + تجميع | ❌ | ✅ HNSW | 8,192 | موجود بالفعل على MongoDB؛ مستند + متجه في آن واحد |
| Redis (VSS) | استضافة ذاتية / Redis Cloud | RSALv2 / SSPL | ✅ (RediSearch) | ✅ | ❌ | ❌ | ❌ RAM‑only | 32,768 | زمن استجابة فائق القليل؛ طبقة تخزين مؤقت للبحث المتجهي |
| Marqo | سحابة / استضافة ذاتية | Apache 2.0 | ✅ | ❌ | ❌ | ✅ تركيز أصلي | ✅ | متنوع | متعدد الوسائط من الطرف إلى الطرف: صورة + نص + فيديو |
بعض الأشياء التي لا تتناسب مع الجدول
تعدد المستأجرين في Turbopuffer مبني حول عدد كبير جدًا من المساحات الاسمية. رسالته العامة وقصص العملاء تبرز أعباء عمل مثل مجموعة Notion الضخمة ذات المساحات الاسمية الكثيفة. إذا كان كل مستخدم أو مؤسسة تحتاج إلى بحث متجهي معزول، يمكن لهذا النموذج تغيير الاقتصاديات، لكن لا يزال من الضروري اختبار شكل المستأجر الخاص بك.
وضع LanceDB المدمج هو أقرب شيء إلى “SQLite للبحث المتجهي”. يعمل داخل العملية، لا يتطلب خادمًا، ويعمل في Lambda وCloudflare Workers وبيئات الحافة. يجعل تنسيق Lance العمودي العملية المدمجة عملية على نطاق حقيقي.
Chroma أقوى في بيئات التطوير/الاختبار ونشر التطبيقات الصغيرة. إذا كنت تستهدف مجموعات بيانات ضخمة، أو توفر عالي، أو عمليات تعتمد على القرص، أو بحثًا هجينًا من الدرجة الأولى، قيّم مخزنًا موجهًا للإنتاج قبل ترقية النموذج الأولي إلى البنية التحتية.
Vespa هو ما تلجأ إليه عندما يكون الاسترجاع مجرد نصف المنتج. يجمع بين الاسترجاع المعجمي، والبحث عن أقرب الجيران، والمُتَجَهات، وتعبيرات الترتيب، والتجميع، والخدمة عبر الإنترنت. هذه القوة حقيقية، لكن تعقيد التشغيل والنمذجة كذلك. يناسب فرق البحث/التوصية أكثر من “إضافة بحث متجهي إلى تطبيق CRUD الخاص بي”.
ClickHouse يندرج في النقاش عندما يكون البحث مرتبطًا بالتحليلات. إذا كان مصدر الحقيقة لديك هو الأحداث أو السجلات أو الآثار أو المقاييس، فإن ClickHouse يحتفظ بمسافة المتجه، والتصفية، والتجميع، وفهرسة النص الكامل الجادة في محرك SQL واحد. ليس قاعدة بيانات متجهية مُصممة خصيصًا، لكنه غالبًا الإجابة الصحيحة المملة للاسترجاع التحليلي.
المتجهات المتناثرة هي الطريقة التي تحصل بها على مطابقة كلمات مفتاحية بجودة BM25 داخل فهرس المتجهات — دون تشغيل محرك نص كامل منفصل. Qdrant وElasticsearch لديهما تطبيقات ناضجة بشكل خاص هنا. إذا كان البحث الهجين أمرًا حاسمًا وكان بنية نظامين عائقًا، فإن دعم المتجهات المتناثرة هو ما يجب البحث عنه.
اختيار الوقت المناسب عندما تتجاوز قدرات pgvector
- منتج SaaS مع عزل لكل مستأجر → Turbopuffer
- تصفية بيانات وصفية معقدة على نطاق واسع → Qdrant
- موجود بالفعل على مجموعة Elastic/ELK → Elasticsearch مع DiskBBQ
- متجر AWS يرغب في مفتوح المصدر → OpenSearch
- منصة بحث/توصية مع احتياجات ترتيب جدية → Vespa
- تحليلات، مراقبة، بحث في السجلات/الأحداث → ClickHouse
- مقياس المليار على الخوادم الداخلية / مستضاف ذاتيًا → Milvus
- حافة / خالية من الخوادم / متعددة الوسائط → LanceDB
- تطبيق JS صغير، موقع وثائق، أو تجربة بحث أصلية على الحافة → Orama
- صفر عمليات، التكلفة ثانوية → Pinecone
- متعدد الوسائط أولًا (صور، فيديو، صوت) → Marqo
- موجود بالفعل على MongoDB → Atlas Vector Search
- موجود بالفعل على Postgres، وتحتاج مساحة رأسية إضافية → Supabase Vector أو Neon (كلاهما يديران pgvector مع أدوات أفضل)
الشيء الوحيد الذي يجب عدم فعله
لا تستخدم البحث المتجهي كبحث نصي غير دقيق للأشياء التي لها إجابات صحيحة.
“اعثر لي على المستخدم بالبريد الإلكتروني dan@example.com” ليس مشكلة بحث متجهية. “اعثر على الطلب بالمعرف ORD-12345” ليس كذلك أيضًا. تضمين ORD-12345 والبحث بتشابه جيب التمام سيعيد شيئًا — لكنه قد يكون غير صحيح. المعرف له إجابة صحيحة. التطابق التقريبي على معرف هو خطأ.
البحث المتجهي يعيد الأكثر تشابهًا في مجموعة البيانات الخاصة بك، حتى عندما لا يكون هناك شيء ذي صلة فعليًا. لا يعرف متى لا توجد إجابة جيدة. هذا مقبول للوثائق ذات الصلة. لكنه مشكلة خطيرة للبحث عن سجل دقيق، حيث أن إجابة خاطئة بثقة أسوأ من نتيجة فارغة.
ينطبق نفس المبدأ في الاتجاه المعاكس: لا تستخدم البحث النصي الكامل (FTS) للاستعلامات التي يصف فيها المستخدم مفهومًا. “مقالات حول اتخاذ قرارات صعبة في ظل عدم اليقين” لا تحتوي على كلمات مفتاحية موثوقة. سيعيد FS إما ضوضاء أو لا شيء. استخدم الأداة المناسبة لشكل الاستعلام.
الصورة الكاملة
معظم أنظمة البحث في الإنتاج تحتاج إلى أكثر من طبقة واحدة:
pg_trgmللأسماء، الأخطاء المطبعية، الإكمال التلقائي- FTS /
pg_searchللبحث النصي القائم على الكلمات المفتاحية - pgvector للاستعلامات الدلالية والمفهومية
- دمج RRF للواجهات التي يخلط فيها المستخدم أنواع الاستعلامات
- الفهارس العادية للمعرفات الدقيقة، الفلاتر، والقوائم المرتبة
هذه ليست أدوات متنافسة. إنها مكملة. نظام بحث مُصمم جيدًا يختار الطبقة المناسبة لكل شكل استعلام — وعندما تتقاطع أشكال الاستعلامات، يشغل عدة طبقات ويجمع النتائج.
الفرق التي تُصدر ميزات بحث جيدة تفهم كامل المكدس. الفرق التي لا تفهم تلجأ إلى قاعدة بيانات متجهية، تُضمّن كل شيء، وتتساءل لماذا أحيانًا تعود عمليات البحث الدقيقة بسجل خاطئ.