DanLevy.net

البحث الدلالي بالمتجهات وموضوعات أخرى لكسب الأصدقاء والمحبين

مشهد البحث الكامل: البحث المطابق، والتقريبي، والدلالي، والهجين — ومتى تجمع بينها كلها.

البحث ليس شيئًا واحدًا، والبحث الدلالي ليس بديلًا عن بقية أنواعه.

مشهد البحث المتجهي: مقارنة 16 خيارًا

قارن بين أساليب النشر، والتراخيص، وقدرات البحث، ومدى ملاءمة كل خيار لأحمال العمل. ترد شروحات الأعمدة وأمثلة SQL أدناه.

كيفية قراءة هذه المقارنة

قاعدة البياناتالنشرالترخيصالبحث الهجينالمتجهات المتناثرةواجهة الاستعلامالتضمين متعدد الوسائط المدمجفهرس على القرصحدود أبعاد المتجهأفضل ملاءمة
pgvectorاستضافة ذاتية / مُدار (Supabase، Neon، RDS)مفتوح المصدر (PostgreSQL)يدوي (RRF عبر SQL)❌✅ SQL كامل❌✅ ‏HNSW على القرص‏16,000 للتخزين؛ ‏2,000 للفهرسة vectorاستخدام PostgreSQL مسبقًا؛ أعداد متجهات متوسطة
Qdrantاستضافة ذاتية / سحابيApache 2.0✅ ‏BM25 أصلي✅ دعم ناضج❌ ‏(REST/gRPC)❌✅‏65,535استعلامات مفلترة على نطاق واسع؛ بيانات وصفية معقدة
Weaviateاستضافة ذاتية / سحابيBSD 3✅ ‏BM25 أصلي + ‏RRF✅❌ ‏(GraphQL / gRPC)✅ عبر الوحدات✅‏65,535أنماط وصول GraphQL؛ تحويل متجهي مدمج
Pineconeسحابي فقطمملوك✅ (أُضيف في 2024)✅❌❌✅ (بلا خوادم)‏20,000بساطة الخدمة المُدارة؛ من دون فريق تشغيل
Milvus / Zillizاستضافة ذاتية / سحابي (Zilliz)Apache 2.0✅ أصلي✅✅ شبيه بـ SQL (لغة استعلام Milvus)✅✅ ‏DiskANN‏32,768نطاق المليارات؛ نشر مؤسسي داخل مقر المؤسسة
Chromaمضمّن / استضافة ذاتيةApache 2.0❌❌❌❌❌‏65,535التطوير المحلي والنمذجة الأولية فقط
LanceDBمضمّن / سحابيApache 2.0✅❌✅ ‏SQL عبر DataFusion✅ أصلي✅ (تنسيق Lance)غير محدودالحافة / بلا خوادم؛ بحيرة بيانات متعددة الوسائط
Oramaمضمّن / سحابيApache 2.0✅ نص كامل + متجهات❌❌❌❌يختلفتطبيقات JS/الحافة؛ بحث خفيف للمواقع والتطبيقات
Turbopufferسحابي فقط (بلا خوادم)مملوك✅ ‏BM25 + متجهات❌❌❌✅ (تخزين الكائنات)‏16,000برمجيات SaaS متعددة المستأجرين؛ ملايين مساحات الأسماء
Elasticsearchاستضافة ذاتية / Elastic CloudSSPL / AGPLv3✅ ‏RRF + ‏ELSER المتناثر✅ ‏(ELSER)✅ ‏Query DSL❌✅ ‏DiskBBQ‏4,096استخدام حزمة Elastic مسبقًا؛ بحث مؤسسي هجين
OpenSearchاستضافة ذاتية / مُدار عبر AWSApache 2.0✅ ‏RRF + البحث العصبي✅✅ ‏Query 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 CloudRSALv2 / SSPL✅ ‏(RediSearch)✅❌❌❌ في الذاكرة فقط‏32,768زمن استجابة بالغ الانخفاض؛ بحث متجهي في طبقة التخزين المؤقت
Marqoسحابي / استضافة ذاتيةApache 2.0✅❌❌✅ تركيز أصلي✅يختلفمتعدد الوسائط من البداية إلى النهاية: صورة + نص + فيديو

«العثور على مستخدم بعنوان البريد الإلكتروني dan@example.com» و«العثور لي على مقالات عن تصحيح الأخطاء بصفتي مهندسًا جديدًا» يوصفان كلاهما بأنهما بحث، لكن لا يكاد يجمعهما شيء من ناحية المشكلة الهندسية. للأول إجابة صحيحة وفحص فهرس بتعقيد O(log n). أما الثاني فلا إجابة صحيحة له — بل صلة فقط — ويتطلب فهم اللغة والنية والمعنى.

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

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

النصف المعجمي والضبابي من الصورة — tsvector وpg_trgm وpg_search — موضح في دليل البحث النصي في Postgres لعام 2026.


المصطلحات المستخدمة في هذا الدليل

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

البحث المعجمي — بحث يستند إلى المطابقة التامة للكلمات والرموز. سريع وحتمي وصحيح للمصطلحات المعروفة. لكنه لا يفهم المرادفات أو إعادة الصياغة أو المكافئات عبر اللغات.

البحث الدلالي — بحث يستند إلى المعنى بدلًا من الرموز. يمكن لاستعلام عن «كيف أتعامل مع انتهاء المهلة» أن يطابق مستندًا بعنوان «تهيئة سياسات إعادة المحاولة» من دون كلمات مشتركة، لأن التضمينين متقاربان هندسيًا.

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

FTS (البحث في النص الكامل) — البحث المعجمي المدمج في Postgres، والمدعوم بـ tsvector / tsquery. يقسم النص إلى رموز، ويستخلص جذورها، ويفهرسه لاستعلامات الكلمات المفتاحية. قوي للنثر والبحث عن المصطلحات التامة؛ لكنه لا يرى المعنى.

BM25 — خوارزمية لترتيب نتائج البحث المعجمي (تستخدمها Elasticsearch وQdrant وغيرهما). تسجل النتائج وفق تكرار المصطلح، مع ترجيحه بحسب مدى ندرته في كامل مجموعة البيانات. أفضل من مطابقة الكلمات المفتاحية الخام؛ لكنها تظل معجمية.

HNSW (العالم الصغير الهرمي القابل للملاحة) — الفهرس القياسي التقريبي لأقرب الجيران في البحث المتجهي. ينشئ رسمًا بيانيًا طبقيًا للتقارب من أجل استعلامات تشابه سريعة وعالية الاستدعاء. تستخدمه pgvector وQdrant وWeaviate ومعظم الأدوات الأخرى.

RRF (دمج الرتب التبادلية) — خوارزمية لدمج قوائم النتائج المرتبة القادمة من أنظمة استرجاع متعددة. تعتمد على موضع النتيجة في الترتيب فقط، ولا تحتاج إلى تطبيع الدرجات. تحصل النتيجة التي تحتل ترتيبًا مرتفعًا في قائمتي FTS والمتجهات على درجة مجمعة أقوى من نتيجة تتفوق في قائمة واحدة فقط.


كيف تعثر التضمينات على المحتوى المرتبط

تحوّل التضمينات المتجهية النص (أو الصور أو الصوت وغير ذلك) إلى قائمة من الأرقام — أي نقطة في فضاء عالي الأبعاد. ويُدرَّب نموذج التضمين بحيث تصل النصوص المتقاربة دلاليًا إلى نقاط متقاربة في ذلك الفضاء. ينتهي الأمر بكلمتي “Dog” و”canine” متقاربتين. أما عبارتا “Running a marathon” و”running a Python script” فتبتعدان عن بعضهما، رغم اشتراكهما في كلمة واحدة.

يبحث البحث عن التشابه في ذلك الفضاء عن المستندات التي يقترب معناها أكثر من معنى الاستعلام، بغض النظر عن التطابق الحرفي للكلمات.

وهذا يعني أن:

لا يستطيع البحث المعجمي (tsvector، pg_trgm) فعل أي من ذلك. فهو يعمل على الكلمات والمحارف، لا على المعنى. الأداتان ليستا بديلين متكافئين — إذ تحل كل منهما نوعًا مختلفًا من المشكلات.


متى يتفوق pgvector

عند بناء RAG. يسترجع التوليد المعزَّز بالاسترجاع (Retrieval-Augmented Generation) مقاطع المستندات الأقرب من حيث المعنى إلى سؤال المستخدم، ثم يمررها إلى نموذج لغوي بوصفها سياقًا. خطوة الاسترجاع هذه عملية متجهية. سيفوّت FTS إعادة الصياغة والمرادفات والتطابقات المفاهيمية التي قد يعبّر بها مقطع ذو صلة بطريقة مختلفة. وتتمثل أفضلية pgvector على مخزن متجهات مستقل في أنه يعمل داخل مثيل Postgres الموجود لديك — فلا توجد خدمة منفصلة لنشرها أو تشغيلها أو مزامنة البيانات معها.

عندما يصف المستخدمون ما يريدونه، لا ما ينبغي البحث عنه. لا تحتوي عبارة “Articles about building confidence as a new manager” على كلمات مفتاحية يُرجَّح ظهورها بشكل موثوق في المنشورات ذات الصلة. وقد لا تستخدم عبارة “A lightweight framework for handling side effects” الكلمات نفسها حرفيًا في الوثائق. يطابق البحث المتجهي القصد، لا التهجئة.

العثور على العناصر المتشابهة. منتجات ذات صلة، أو تذاكر دعم متشابهة، أو تقارير أخطاء مكررة، أو مقالات قد تهمك أيضًا. إن عبارة “Find issues similar to this one” هي بحث عن أقرب الجيران — تضمّن العنصر، ثم اعثر على جيرانه الهندسيين. لكن هناك تحذير مهم: يعيد البحث المتجهي نتائج دائمًا، حتى عندما لا يكون أي منها مشابهًا فعلًا. في حالات إزالة التكرار والتوصيات، صفِّ النتائج باستخدام حد أدنى للتشابه (مثلًا، تشابه جيب التمام ≥ 0.80) لتجنب عرض مطابقات منخفضة الثقة كما لو كانت ذات معنى.

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

البحث متعدد اللغات. تربط نماذج التضمين متعددة اللغات المحتوى المتكافئ دلاليًا عبر اللغات بمتجهات متقاربة. ويمكن لاستعلام بالإسبانية عن “perder peso” أن يطابق مقالًا إنجليزيًا عن “sustainable weight loss habits” — لا توجد رموز مشتركة، لكن المعنى الأساسي واحد. يتطلب FTS إعداد قاموس خاص بكل لغة، ويتعامل بصورة سيئة مع الاستعلامات العابرة للغات. أما pg_trgm فهو مستقل عن اللغة، لكنه إملائي لا دلالي.

إعداد pgvector

من تثبيت الامتداد إلى تنفيذ استعلام التشابه، لا يتطلب الإعداد سوى عدد قليل من عبارات SQL:

CREATE EXTENSION IF NOT EXISTS vector;
ALTER TABLE documents ADD COLUMN embedding vector(1536);
-- HNSW is usually the first index to try for moderate-size datasets
CREATE INDEX documents_embedding_idx
ON documents USING hnsw (embedding vector_cosine_ops);
-- Semantic search query
SELECT id, title, 1 - (embedding <=> $1::vector) AS similarity
FROM documents
ORDER BY embedding <=> $1::vector
LIMIT 10;

<=> هي مسافة جيب التمام. ويعطي 1 - cosine_distance تشابه جيب التمام (‏1.0 = متطابق، و0.0 = متعامد). وبالنسبة إلى ivfflat (البديل الأقدم والأسرع في البناء)، استخدم lists = sqrt(row_count) كنقطة بداية.

أين يعيد البحث المتجهي الإجابة الخاطئة


اجمع الكلمات المفتاحية والمتجهات للاستعلامات المختلطة

تُعد الوثائق التقنية أوضح مثال على حالة لا تكفي فيها أي من الأداتين بمفردها.

فالمستخدمون الذين يبحثون عن "how to configure timeouts" يحتاجون إلى مطابقة مفاهيمية: إذ لا يحتوي مقال بعنوان "Setting retry policies and connection limits" على كلمات مفتاحية مشتركة، لكنه بالضبط ما يحتاجون إليه.

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

يتولى البحث المتجهي الاستعلامات المفاهيمية. ويتولى FTS المصطلحات الحرفية. ولا يتعامل أي منهما مع الحالتين جيدًا بمفرده.

الحل هو البحث الهجين: شغّل النظامين معًا وادمج النتائج.

ادمج النتائج المرتبة باستخدام RRF

دمج الرتب التبادلي (Reciprocal Rank Fusion، أو 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_score
FROM rrf
JOIN documents d ON d.id = rrf.id
ORDER BY rrf_score DESC
LIMIT 10;

العدد 60 في المقام هو ثابت RRF. تؤدي القيم الأعلى إلى تخفيف الفروق بين مواضع الترتيب، بينما تضخمها القيم الأقل. وتعمل القيمة الافتراضية 60 جيدًا مع معظم أنواع المحتوى.

يتجنب RRF المشكلة الأصعب المتمثلة في توحيد ts_rank (وهي درجة تعتمد على التكرار اللوغاريتمي) مع مسافة جيب التمام (وهي مقياس هندسي). فهما غير قابلين للمقارنة. ولا يسأل RRF إلا: «ما مدى ارتفاع ترتيب هذه النتيجة في كل قائمة؟»

أضف الترايغرامات للتعامل مع الأخطاء الإملائية والأسماء

في البحث الموجه للمستخدمين على محتوى مختلط — حيث قد يبحث المستخدم في الجلسة نفسها عن اسم شخص، أو مفهوم، أو مصطلح حرفي — يتولى الدمج ثلاثي الاتجاهات الحالات كلها:

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_score
FROM rrf
JOIN documents d ON d.id = rrf.id
ORDER BY rrf_score DESC
LIMIT 10;

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


طابق كل واجهة بحث مع أنواع الاستعلامات الخاصة بها

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

الواجهةما الذي يستعلم عنه المستخدمونالطبقات الموصى بها
البحث في المدونة / الوثائقالكلمات المفتاحية + المفاهيمFTS + pgvector (RRF)
البحث عن اسم مستخدم / عميلالأسماء التي تحتوي على أخطاء إملائيةpg_trgm
البحث عن المنتجاتالأسماء والأوصاف وعبارة «مشابه لـ»pg_trgm + FTS + pgvector
إزالة التكرار في تذاكر الدعم«مشكلات مشابهة لهذه»pgvector فقط
البحث الداخلي عن SKU / الطلباتالمعرّفات الدقيقةفهرس B-tree
RAG فوق قاعدة معرفية كبيرةالأسئلة باللغة الطبيعيةpgvector (مستندات مجزأة)
«قد يعجبك أيضًا» في التجارة الإلكترونيةالتشابه السلوكي + الدلاليpgvector
الإكمال التلقائيالبادئة، مع تحمّل الأخطاء الإملائيةpg_trgm

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

أضف طبقة بحث عندما يفشل نوع من الاستعلامات

أضف طبقة عندما يظهر نمط فشل لا تستطيع الطبقة الحالية إصلاحه:


متى تتجاوز pgvector

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

كيف تقرأ المقارنة

البحث الهجين يعني أن بحث الكلمات المفتاحية باستخدام BM25 وتشابه المتجهات يعملان ضمن استعلام واحد، ثم تُدمج النتائج عبر RRF. ومن دونه، إما أن تختار نمط بحث واحدًا، أو تدمج الاستعلامين بنفسك.

المتجهات المتناثرة تتجاوز BM25. يحتوي المتجه المتناثر SPLADE على نحو 30,000 بُعد (بُعد واحد لكل مصطلح في المفردات)، ويكون نحو 98% منها أصفارًا. تخبرك المواضع غير الصفرية بالمصطلحات المهمة ودرجة أهميتها. فالاستعلام عن «dogs» يضع وزنًا أيضًا على «canine» و«pet» — دقة على مستوى BM25، مع توسيع للمصطلحات داخل فهرس متجهي. إذا كان هذا العمود يساوي false، فستحتاج إلى طبقة FTS منفصلة للاستعلامات التي تتطلب مطابقة المصطلحات بدقة.

# SPLADE: ~30,000 dims, ~60 non-zero — only relevant vocabulary positions fire
def 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 expression
SELECT id, title, 1 - (embedding <=> $1) AS score
FROM documents
WHERE tenant_id = $2
AND category = ANY($3::text[])
AND created_at > NOW() - INTERVAL '90 days'
ORDER BY embedding <=> $1
LIMIT 10;
# Qdrant: equivalent filter as a Python object — same result, more ceremony
results = 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,
)

الدعم الأصلي للوسائط المتعددة يعني أن قاعدة البيانات توفر نماذج تضمين للمحتوى غير النصي. تعطيها عنوان URL لصورة خام، وهي تتولى تحويلها إلى متجه. معظم قواعد البيانات غير مرتبطة بنموذج تضمين بعينه — وأنت المسؤول عن خط أنابيب التضمين. وتغلق Marqo وWeaviate (عبر وحدات CLIP/ImageBind) هذه الحلقة.

# Marqo: POST raw images, query with text — no external embedding step
mq.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 المقيمة في الذاكرة أن تتطلب عدة غيغابايتات من الذاكرة لكل مليون متجه ذي 1536 بُعدًا، بعد احتساب المتجهات الخام، والحمل الإضافي للرسم البياني، والبيانات الوصفية. غالبًا ما توازن البدائل الأصلية للقرص — مثل Milvus DiskANN وElasticsearch DiskBBQ وتنسيق Lance في LanceDB وطبقة التخزين الكائني في Turbopuffer — بين قدر من زمن الاستعلام وتكلفة بنية تحتية أقل. وفي أحمال RAG التي يهيمن فيها زمن النموذج أصلًا، يستحق هذا التبادل القياس المعياري في كثير من الأحيان.

الحد الأقصى للأبعاد عملية ترحيل كامنة في معماريتك. يستخدم text-embedding-3-large عدد 3072 بُعدًا، ويمكن لـ Jina v3 إنتاج تضمينات أكبر، وتواصل النماذج البحثية دفع الأحجام إلى أعلى. تنشر بعض الخدمات المُدارة حدودًا قصوى صارمة للأبعاد؛ بينما توثق خدمات أخرى حدودًا مرتفعة أو لا تضع حدًا عمليًا لنماذج التضمين المعتادة. راجع الوثائق الحالية قبل الالتزام. اختر خيارًا يترك هامشًا للنمو؛ فترحيل فهرس متجهي لأنك اصطدمت بسقف الأبعاد عملية مؤلمة.

مفاضلات تشغيلية لا يستطيع الجدول إظهارها

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

وضع LanceDB المضمّن هو أقرب ما يكون إلى «SQLite للبحث المتجهي». يعمل داخل العملية، ولا يتطلب خادمًا، ويعمل في Lambda وCloudflare Workers وبيئات الحافة. ويجعل تنسيق Lance العمودي التشغيل المضمّن عمليًا على نطاق حقيقي.

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

Vespa هي ما تلجأ إليه عندما لا يكون الاسترجاع سوى نصف المنتج. فهي تجمع بين الاسترجاع المعجمي، والبحث بأقرب الجيران، والموترات، وتعبيرات الترتيب، والتجميع، والتقديم عبر الإنترنت. هذه القوة حقيقية، وكذلك التعقيد التشغيلي وتعقيد النمذجة. وهي تلائم فرق البحث/التوصيات أكثر من حالة «أضف البحث الدلالي إلى تطبيق CRUD لديّ».

ينبغي أن تكون ClickHouse ضمن الخيارات المطروحة عندما يكون البحث مرتبطًا بالتحليلات. إذا كانت قاعدة الحقيقة لديك هي الأحداث أو السجلات أو آثار التتبع أو المقاييس، فإن ClickHouse يجمع مسافة المتجه، والتصفية، والتجميع، والفهرسة الجادة للنص الكامل في محرك SQL واحد. إنها ليست قاعدة بيانات متجهية متخصصة، لكنها غالبًا الإجابة الصحيحة المملة للاسترجاع التحليلي.

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

اختر المخزن وفقًا لحِمل العمل


لا تضمّن المعرّفات وتتوقع مطابقات تامة

لا تستخدم البحث المتجهي كبحث نصي تقريبي للأشياء التي لها إجابات صحيحة.

«اعثر لي على المستخدم الذي بريده الإلكتروني هو dan@example.com» ليست مسألة بحث متجهي. و«اعثر على الطلب ذي المعرّف ORD-12345» ليست كذلك. سيؤدي تضمين ORD-12345 والبحث باستخدام تشابه جيب التمام إلى إرجاع شيء ما — لكنه قد يكون خاطئًا. للمعرّف إجابة صحيحة. والمطابقة التقريبية للمعرّف خطأ.

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

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


ابنِ البحث حول شكل الاستعلام

تحتاج معظم أنظمة البحث الإنتاجية إلى أكثر من طبقة واحدة:

هذه الأدوات ليست متنافسة؛ بل متكاملة. يختار نظام البحث المبني جيدًا الطبقة المناسبة لكل شكل من أشكال الاستعلام — وعندما تتداخل أشكال الاستعلام، يشغّل طبقات متعددة ويدمج النتائج.

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