البحث المُصفى باستخدام StructArray

استخدم هذه الصفحة لإضافة تصفية قيمية إلى البحث المتجهي في حقول StructArray. تتكون تصفية StructArray من مستويين: تعمل المرشحات على مستوى الصف على تحديد الكيانات الأصلية، بينما تحدد المرشحات على مستوى العنصر عناصر Struct التي تشارك في البحث المتجهي على مستوى العنصر.

تستخدم هذه الصفحة مجموعة « tech_articles » من «إنشاء حقل StructArray». تحتوي المجموعة على حقل StructArray باسم « chunks »، مع حقول فرعية قياسية مثل « section » و« page » و« quality_score » و« has_code »، بالإضافة إلى حقول فرعية متجهة للبحث.

اختر نوع المرشح

الهدفالاستخدامسلوك النتيجة
التصفية حسب حقل قياسي من المستوى الأعلى، مثل category.تعبير تصفية عادي.يختار الكيانات الأصلية قبل البحث أو أثناءه.
تقييد البحث المتجهي على مستوى العناصر ليقتصر على عناصر Struct التي تتطابق مع الشروط القياسية.element_filter.يبحث فقط في عناصر Struct المطابقة ويمكنه إرجاع إزاحات العناصر المطابقة.
تحديد الكيانات بناءً على ما إذا كانت أي عناصر من Struct أو جميعها أو عدد محدد منها تتطابق مع المسند.MATCH_ANY، MATCH_ALL ، MATCH_LEAST ، MATCH_MOST ، أو MATCH_EXACT.التصفية على مستوى الصف. لا تُرجع هذه العوامل إزاحات بحد ذاتها.

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

التصفية حسب الحقول ذات المستوى الأعلى

استخدم تعبيرات التصفية العادية عندما تنتمي الشرط إلى الكيان الأصلي، وليس إلى عنصر Struct فردي. يعمل هذا مع كل من البحث EmbeddingList والبحث على مستوى العناصر.

from pymilvus import MilvusClient
from pymilvus.client.embedding_list import EmbeddingList

client = MilvusClient(
    uri="http://localhost:19530",
    token="root:Milvus",
)

query = EmbeddingList()
query.add([0.12, 0.21, 0.32, 0.44])
query.add([0.18, 0.23, 0.29, 0.36])

results = client.search(
    collection_name="tech_articles",
    data=[query],
    anns_field="chunks[emb_list_vector]",
    filter='category == "search"',
    limit=3,
    output_fields=[
        "doc_id",
        "title",
        "category",
        "chunks[text]",
        "chunks[section]",
    ],
)

يختار التصفية أعلاه فقط الكيانات التي يكون حقل المستوى الأعلى الخاص بـ « category » فيها هو « "search" ». ولا يحدد عنصر Struct واحدًا مطابقًا.

استخدم element_filter(structArrayField, predicate) عندما يجب أن تنطبق الشروط القياسية على نفس عنصر Struct الذي يشارك في البحث المتجهي على مستوى العنصر. داخل المسند، استخدم $[subfield] للإشارة إلى الحقول الفرعية القياسية لعنصر Struct الحالي.

query_vector = [0.19, 0.24, 0.30, 0.37]

filter_expr = (
    'category == "search" && '
    'element_filter(chunks, '
    '$[section] == "index" && '
    '$[quality_score] > 0.9 && '
    '$[has_code] == true)'
)

results = client.search(
    collection_name="tech_articles",
    data=[query_vector],
    anns_field="chunks[emb]",
    filter=filter_expr,
    limit=5,
    output_fields=[
        "doc_id",
        "title",
        "chunks[text]",
        "chunks[section]",
        "chunks[page]",
        "chunks[quality_score]",
        "chunks[has_code]",
    ],
)

for hits in results:
    for hit in hits:
        print(
            "doc_id:", hit["id"],
            "distance:", hit["distance"],
            "offset:", hit.get("offset"),
            "entity:", hit["entity"],
        )

في هذا المثال، يختار المسند ذو المستوى الأعلى category == "search" الكيانات المرشحة، ويقصر element_filter البحث المتجهي على مستوى العنصر على المجموعات التي تتطابق فيها section و quality_score و has_code جميعها في نفس عنصر Struct.

تحذير

عند دمج مسند من المستوى الأعلى مع element_filter ، ضع element_filter في نهاية التعبير. لا يمكن أن يحتوي تعبير التصفية إلا على element_filter واحد فقط، ولا يمكنك تضمين element_filter أو MATCH_* داخل عامل StructArray آخر.

تصفية الكيانات باستخدام عوامل MATCH

استخدم مشغلات MATCH_* عندما يتعين على التصفية تحديد ما إذا كانت الكيانات الأصلية مؤهلة بناءً على عناصر Struct الخاصة بها. هذه المشغلات هي عوامل تصفية على مستوى الصف: فهي تحدد الكيانات، ولكنها لا تُرجع إزاحات العناصر من تلقاء نفسها.

المشغلاستخدمه عندمامثال
MATCH_ANYيجب أن يستوفي عنصر Struct واحد على الأقل الشرط.MATCH_ANY(chunks, $[section] == "index")
MATCH_ALLيجب أن تستوفي جميع عناصر Struct الشرط.MATCH_ALL(chunks, $[quality_score] > 0.5)
MATCH_LEASTيجب أن تستوفي عناصر Struct التي لا يقل عددها عن N الشرط.MATCH_LEAST(chunks, $[has_code] == true, threshold=2)
MATCH_MOSTيجب أن تستوفي عناصر Struct التي لا يتجاوز عددها N الشرط.MATCH_MOST(chunks, $[section] == "appendix", threshold=1)
MATCH_EXACTيجب أن تستوفي عناصر Struct التي يبلغ عددها بالضبط N الشرط.MATCH_EXACT(chunks, $[section] == "summary", threshold=1)
filter_expr = (
    'category == "search" && '
    'MATCH_ANY(chunks, $[section] == "index" && $[quality_score] > 0.9)'
)

results = client.search(
    collection_name="tech_articles",
    data=[query],
    anns_field="chunks[emb_list_vector]",
    filter=filter_expr,
    limit=3,
    output_fields=[
        "doc_id",
        "title",
        "category",
        "chunks[text]",
        "chunks[section]",
        "chunks[quality_score]",
    ],
)

استخدم " MATCH_ANY " هنا لأن نتيجة البحث في EmbeddingList تكون على مستوى الكيان. يتطلب المرشح أن تكون هناك قطعة واحدة على الأقل في الكيان من نوع " "index" " ذات جودة عالية، لكن نتيجة البحث نفسها لا تزال تمثل الكيان الأصلي.

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

from pymilvus import AnnSearchRequest, RRFRanker

query_vector = [0.19, 0.24, 0.30, 0.37]

title_req = AnnSearchRequest(
    data=[query_vector],
    anns_field="title_vector",
    limit=10,
)

chunk_req = AnnSearchRequest(
    data=[query_vector],
    anns_field="chunks[emb]",
    limit=10,
    expr='element_filter(chunks, $[section] == "index" && $[quality_score] > 0.9)',
)

results = client.hybrid_search(
    collection_name="tech_articles",
    reqs=[title_req, chunk_req],
    ranker=RRFRanker(),
    filter='category == "search"',
    limit=5,
    output_fields=[
        "doc_id",
        "title",
        "category",
        "chunks[text]",
        "chunks[section]",
        "chunks[quality_score]",
    ],
)

تطبق وسيطة filter شرط الكيان من المستوى الأعلى، بينما يقيد expr في chunk_req طلب المتجه على مستوى عنصر StructArray فقط. للاطلاع على تركيبات البحث الهجين المدعومة والقيود الخاصة بالإصدار، راجع البحث الهجين باستخدام StructArray وقيود StructArray.

ملخص دعم المسندات

استخدم الحقول الفرعية القياسية في مسندات StructArray. لا تُعتبر الحقول الفرعية المتجهة مدخلات قياسية للمسندات.

نوع الحقل الفرعيأمثلة نموذجية على المسندات
BOOL$[has_code] == true، !($[has_code] == true)
أنواع الأعداد الصحيحة$[page] >= 2, $[page] in [1, 2, 3]
FLOAT، DOUBLE$[quality_score] > 0.9، 0.7 < $[quality_score] < 0.95
VARCHAR$[section] == "index"، $[text] like "range%"
الحقول الفرعية للمتجهاتغير مدعومة كمدخلات للمسندات القياسية في $[...]. استخدم الحقول الفرعية للمتجهات من خلال البحث المتجهي بدلاً من ذلك.

بالنسبة للحالات غير المدعومة مثل مسارات JSON، ووظائف حاويات المصفوفات، ووظائف مطابقة النص، والمسندات ذات القيمة null في $[...] ، ووظائف Geometry، وتعبيرات Timestamptz، واستدعاءات الوظائف العامة، راجع StructArray Operators.

الأخطاء الشائعة

  • استخدام $[subfield] خارج element_filter أو MATCH_*.

  • استخدام chunks.section بدلاً من صيغة مشغل StructArray مثل element_filter(chunks, $[section] == "index").

  • استخدام element_filter عندما تحتاج فقط إلى التصفية على مستوى الصفوف. استخدم MATCH_ANY بدلاً من ذلك إذا كنت تحتاج فقط إلى تحديد الكيانات.

  • توقع أن تُرجع MATCH_* إزاحات العناصر. تختار هذه العوامل الكيانات ولا تحدد عنصرًا مطابقًا واحدًا بمفردها.

  • كتابة المسندات المنطقية المجردة مثل $[has_code]. استخدم مقارنات صريحة مثل $[has_code] == true.

  • وضع element_filter قبل مسند من المستوى الأعلى في نفس تعبير التصفية.

الخطوات التالية

  1. لمراجعة صيغة تصفية StructArray الكاملة، اقرأ «عوامل StructArray».

  2. لتشغيل عمليات البحث المتجهية غير المفلترة أولاً، اقرأ «البحث المتجهي الأساسي باستخدام StructArray».

  3. لإنشاء فهارس قياسية لفلاتر StructArray المستخدمة بشكل متكرر، اقرأ " فهرسة حقول StructArray".

  4. للتحقق من حدود التصفية والبحث الخاصة بكل إصدار، اقرأ " حدود StructArray".