فیلتر

با Qdrant، شما می‌توانید شرایطی را برای جستجو یا بازیابی نقاط تعیین کنید که به این معنی است که می‌توانید به علاوه جستجوهای مشابه بردارها بر اساس ویژگی، همچنین، تنظیم کنید که شرایطی را برای بارگیری و id نقطه تعیین کنید.

تعیین شرایط اضافی مهم است زمانی که همه ویژگی‌های یک شی را نمی‌توان در یک جاسازی بیان کرد. به عنوان مثال، انواع الزامات تجاری مانند در دسترس بودن موجودی، موقعیت کاربر یا محدوده قیمت مورد انتظار.

شرایط فیلتر

Qdrant به شما امکان ترکیب شرایط در بند‌ها می‌دهد. بندها عملیات منطقی مختلفی هستند مانند OR، AND و NOT. بندها می‌توانند به صورت بازگشتی در یکدیگر جای گیرند، بنابراین شما می‌توانید هر عبارت بولیایی را بازسازی کنید.

بیایید به بندهایی که در Qdrant پیاده سازی شده‌اند، نگاهی بیندازیم.

فرض کنید ما دارای مجموعه‌ای از نقاط با بارگیری‌ها هستیم:

[
  { "id": 1, "city": "London", "color": "green" },
  { "id": 2, "city": "London", "color": "red" },
  { "id": 3, "city": "London", "color": "blue" },
  { "id": 4, "city": "Berlin", "color": "red" },
  { "id": 5, "city": "Moscow", "color": "green" },
  { "id": 6, "city": "Moscow", "color": "blue" }
]

باید

مثال:

POST /collections/{نام_مجموعه}/points/scroll

{
    "filter": {
        "must": [
            { "key": "city", "match": { "value": "London" } },
            { "key": "color", "match": { "value": "red" } }
        ]
    }
  ...
}

نقطه فیلتر شده این خواهد بود:

[{ "id": 2, "city": "London", "color": "red" }]

هنگام استفاده از must، بنده تنها زمانی true است که هر شرط موجود در must برآورده شود. به این معنی که must معادل با عملگر AND است.

باید

Should مشابه عملگر OR در SQL است.

مثال:

POST /collections/{نام_مجموعه}/points/scroll

{
    "filter": {
        "should": [
            { "key": "city", "match": { "value": "London" } },
            { "key": "color", "match": { "value": "red" } }
        ]
    }
  ...
}

نقاط فیلتر شده این خواهند بود:

[
  { "id": 1, "city": "London", "color": "green" },
  { "id": 2, "city": "London", "color": "red" },
  { "id": 3, "city": "London", "color": "blue" },
  { "id": 4, "city": "Berlin", "color": "red" }
]

هنگام استفاده از should، بنده تا زمانی که حداقل یک شرط موجود در should برآورده شود، true است. به این معنی که should معادل با عملگر OR است.

must_not

مثال:

POST /collections/{نام_مجموعه}/points/scroll

{
    "filter": {
        "must_not": [
            { "key": "city", "match": { "value": "London" } },
            { "key": "color", "match": { "value": "red" } }
        ]
    }
  ...
}

نقاط فیلتر شده این خواهند بود:

[
  { "id": 5, "city": "Moscow", "color": "green" },
  { "id": 6, "city": "Moscow", "color": "blue" }
]

هنگام استفاده از must_not، زیربنده تنها زمان true است که هیچ یک از شرایط موجود در must_not برآورده نشوند. به این معنی که must_not معادل با عبارت (NOT A) AND (NOT B) AND (NOT C) است.

ترکیب شرایط

استفاده از چندین شرط به صورت همزمان امکان پذیر است:

POST /collections/{collection_name}/points/scroll

{
    "filter": {
        "must": [
            { "key": "city", "match": { "value": "لندن" } }
        ],
        "must_not": [
            { "key": "color", "match": { "value": "قرمز" } }
        ]
    }
  ...
}

نقاط فیلتر شده به صورت زیر خواهند بود:

[
  { "id": 1, "city": "لندن", "color": "سبز" },
  { "id": 3, "city": "لندن", "color": "آبی" }
]

در این حالت، شروط با استفاده از AND ترکیب شده اند.

به علاوه، شرایط می‌توانند به صورت بازگشتی شامل حالت های تو در تو باشند. به عنوان مثال:

POST /collections/{collection_name}/points/scroll

{
    "filter": {
        "must_not": [
            {
                "must": [
                    { "key": "city", "match": { "value": "لندن" } },
                    { "key": "color", "match": { "value": "قرمز" } }
                ]
            }
        ]
    }
  ...
}

نقاط فیلتر شده به صورت زیر خواهند بود:

[
  { "id": 1, "city": "لندن", "color": "سبز" },
  { "id": 3, "city": "لندن", "color": "آبی" },
  { "id": 4, "city": "برلین", "color": "قرمز" },
  { "id": 5, "city": "مسکو", "color": "سبز" },
  { "id": 6, "city": "مسکو", "color": "آبی" }
]

فیلتر کردن شرایط

در بارهٔ مقادیر مختلف، ویژگی‌های مختلف شرایط و نوع داده‌هایی که مورد استفاده قرار می‌گیرند، نگاهی بیان می‌کنیم.

تطبیق

{
  "key": "color",
  "match": {
    "value": "قرمز"
  }
}

برای انواع دیگر، شرایط تطبیق دقیقاً همانند این نمونه هستند، تنها با استفاده از انواع مختلف:

{
  "key": "count",
  "match": {
    "value": 0
  }
}

ساده‌ترین شرط، بررسی می‌کند که آیا مقدار ذخیره شده برابر با مقدار داده شده است یا خیر. اگر چندین مقدار ذخیره شده باشد، حداقل یکی از آن‌ها باید شرط را ارضا کند. این مورد می‌تواند برای بارگیری دیتاهای کلیدی، صحیح‌شماره، و پیام‌های بولیانی مورد استفاده قرار گیرد.

همهٔ تطبیق

از نگارش v1.1.0 به بعد قابل دسترسی است

اگر بخواهید بررسی کنید که آیا مقدار ذخیره شده یکی از چندین مقدار است، می‌توانید از شرط همهٔ تطبیق استفاده کنید. همهٔ تطبیق مقدار داده شده را به عنوان یک عملیات OR منطقی در نظر می‌گیرد. همچنین می‌توان آن را به عنوان IN اشاره داشت.

شما می‌توانید آن را برای بارگیری دیتاهای کلیدی و صحیح‌شماره اعمال کنید.

مثال:

{
  "key": "color",
  "match": {
    "any": ["سیاه", "زرد"]
  }
}

در این مثال، اگر مقدار ذخیره شده سیاه یا زرد باشد، شرط ارضا خواهد شد.

اگر مقدار ذخیره‌شده یک آرایه باشد، باید حداقل یک مقدار داشته باشد که با هر یک از مقادیر داده شده همخوانی داشته باشد. به عنوان مثال، اگر مقدار ذخیره‌شده ["سیاه", "سبز"] باشد، آنگاه شرط ارضا خواهد شد چرا که "سیاه" در ["سیاه", "زرد"] واقع شده است.

همپوشانی منع شده

از نگارش v1.2.0 به بعد قابل دسترسی است

اگر بخواهید بررسی کنید که آیا مقدار ذخیره شده هیچکدام از چندین مقدار است، می‌توانید از شرط همپوشانی منع شده استفاده کنید. همپوشانی منع شده مقدار داده شده را به عنوان یک عملیات NOR منطقی در نظر می‌گیرد. همچنین می‌توان آن را به عنوان NOT IN اشاره داشت.

شما می‌توانید آن را برای بارگیری دیتاهای کلیدی و صحیح‌شماره اعمال کنید.

مثال:

{
  "key": "color",
  "match": {
    "except": ["سیاه", "زرد"]
  }
}

در این مثال، اگر مقدار ذخیره شده هیچ‌کدام از سیاه و زرد نباشد، شرط ارضا خواهد شد.

اگر مقدار ذخیره‌شده یک آرایه باشد، باید حداقل یک مقدار داشته باشد که با هیچ‌کدام از مقادیر داده شده همخوانی نداشته باشد. به عنوان مثال، اگر مقدار ذخیره‌شده ["سیاه", "سبز"] باشد، آنگاه شرط ارضا خواهد شد چرا که "سبز" با "سیاه" یا "زرد" هم‌خوانی ندارد.

کلیدهای تودرتو

از نسخه v1.1.0 به بعد قابل دسترسی است

از آنجا که بار مفتاح یک شی JSON دلخواه است، ممکن است نیاز داشته باشید تا فیلدهای تودرتو را فیلتر کنید.

برای راحتی، ما از یک نحوهٔ مشابه با پروژه Jq استفاده می‌کنیم.

فرض کنید مجموعه‌ای از نقاط با بار زیر را داشته باشیم:

[
  {
    "id": 1,
    "country": {
      "name": "آلمان",
      "cities": [
        {
          "name": "برلین",
          "population": 3.7,
          "sightseeing": ["دروازه براندنبورگ", "رایخ‌استاگ"]
        },
        {
          "name": "مونیخ",
          "population": 1.5,
          "sightseeing": ["میدان ماریان", "پارک المپیا"]
        }
      ]
    }
  },
  {
    "id": 2,
    "country": {
      "name": "ژاپن",
      "cities": [
        {
          "name": "توکیو",
          "population": 9.3,
          "sightseeing": ["برج توکیو", "برج اسکای توکیو"]
        },
        {
          "name": "اوساکا",
          "population": 2.7,
          "sightseeing": ["قلعه اوساکا", "استودیوهای یونیورسال ژاپن"]
        }
      ]
    }
  }
]

شما می‌توانید از نماد نقطه برای جستجوی فیلدهای تودرتو استفاده کنید.

POST /collections/{نام_مجموعه}/points/scroll

{
    "filter": {
        "should": [
            {
                "key": "country.name",
                "match": {
                    "value": "آلمان"
                }
            }
        ]
    }
}

شما همچنین می‌توانید از نحوه [ ] برای جستجوی آرایه با پروژه مقادیر داخلی استفاده کنید.

POST /collections/{نام_مجموعه}/points/scroll

{
    "filter": {
        "should": [
            {
                "key": "country.cities[].population",
                "range": {
                    "gte": 9.0,
                }
            }
        ]
    }
}

این پرس‌وجو تنها نقطهٔ با شناسه 2 را خروجی می‌دهد، زیرا تنها ژاپن شهری با جمعیت بیشتر از ۹٫۰ دارد.

فیلدهای تودرتو همچنین می‌تواند یک آرایه باشد.

POST /collections/{نام_مجموعه}/points/scroll

{
    "filter": {
        "should": [
            {
                "key": "country.cities[].sightseeing",
                "match": {
                    "value": "قلعه اوساکا"
                }
            }
        ]
    }
}

این پرس‌وجو تنها نقطهٔ با شناسه 2 را خروجی می‌دهد، زیرا تنها ژاپن شهری دارای یک مکان دیدنی است که شامل "قلعه اوساکا" است.

فیلتر کردن شی‌های تودرتو

از ورژن 1.2.0 در دسترس است

به طور پیشفرض، شرایط کل پیام را در نظر می‌گیرند.

به عنوان مثال، با داشتن دو پیام در بارگذاری زیر:

[
  {
    "id": 1,
    "dinosaur": "t-rex",
    "diet": [
      { "food": "leaves", "likes": false},
      { "food": "meat", "likes": true}
    ]
  },
  {
    "id": 2,
    "dinosaur": "diplodocus",
    "diet": [
      { "food": "leaves", "likes": true},
      { "food": "meat", "likes": false}
    ]
  }
]

پرس و جوی زیر با این دو پیام همخوانی پیدا می‌کند:

POST /collections/{collection_name}/points/scroll

{
    "filter": {
        "must": [
            {
                "key": "diet[].food",
                  "match": {
                    "value": "meat"
                }
            },
            {
                "key": "diet[].likes",
                  "match": {
                    "value": true
                }
            }
        ]
    }
}

دلیل همخوانی دو پیام فوق این است که هر دو پیام، این دو شرط را ارضا می‌کنند:

  • "t-rex" شرط diet[1].food با مقدار food = meat و diet[1].likes با مقدار likes = true را ارضا می‌کند
  • "diplodocus" شرط diet[1].food با مقدار food = meat و diet[0].likes با مقدار likes = true را ارضا می‌کند

برای فقط به دست آوردن پیام‌هایی که شرایط برای عناصر آرایه را ارضا می‌کنند، به عنوان مثال، پیام با شناسه 1 در این مثال، باید از فیلترهای شی تودرتو استفاده کنید.

فیلترهای شی تودرتو امکان پرس و جو در آرایه‌های شی را مستقل ارائه می‌دهند.

این امر از طریق استفاده از نوع شرط nested قابل دستیابی است که شامل کلید بارگذاری مورد نظر و فیلتر قابل اعمال است.

کلید باید به یک آرایه شی اشاره کند و به صورت اختیاری می‌تواند از نشانه‌گذاری براکت ("data" یا "data[]") استفاده کند.

POST /collections/{collection_name}/points/scroll

{
    "filter": {
        "must": [
            "nested": {
                {
                    "key": "diet",
                    "filter": {
                        "must": [
                            {
                                "key": "food",
                                "match": {
                                    "value": "meat"
                                }
                            },
                            {
                                "key": "likes",
                                "match": {
                                    "value": true
                                }
                            }
                        ]
                    }
                }
            }
        ]
    }
}

منطق همخوانی تغییر کرده تا در سطح عنصر آرایه در بارگذاری اعمال شود.

فیلتر تودرتو به همان روشی کار می‌کند که وقتی یک فیلتر تودرتو را به یک عنصر تکی از یک آرایه اعمال می‌کنید. تا زمانی که حداقل یک عنصر از آرایه با فیلتر تودرتو همخوانی داشته باشد، سند والد به عنوان همخوانی با شرط در نظر گرفته می‌شود.

محدودیت

فیلترهای شی تودرتو شرط has_id را پشتیبانی نمی‌کنند. اگر نیاز به استفاده از آن دارید، آن را در یک بند مجاور must قرار دهید.

POST /collections/{collection_name}/points/scroll

{
    "filter": {
        "must": [
            "nested": {
                {
                    "key": "diet",
                    "filter": {
                        "must": [
                            {
                                "key": "food",
                                "match": {
                                    "value": "meat"
                                }
                            },
                            {
                                "key": "likes",
                                "match": {
                                    "value": true
                                }
                            }
                        ]
                    }
                }
            },
            { "has_id": [1] }
        ]
    }
}

تطبیق متن دقیق

از ورژن 0.10.0 در دسترس است

یک حالت ویژه از شرط match شرط text تطبیق متن است. این به شما امکان می‌دهد تا برای زیرمجموعه‌ها، توکن‌ها یا عبارات خاص درون فیلد متنی جستجو کنید.

متن‌های دقیق که این شرط را ارضا می‌کنند، به تنظیمات فهرست متنی کامل بستگی دارد. تنظیمات در زمان ایجاد فهرست تعریف می‌شود و درون فهرست متنی توصیف می‌شود.

اگر فیلد دارای فهرست متنی نباشد، این شرط بر اساس تطبیق دقیق زیرمجموعه کار می‌کند.

{
  "key": "description",
  "match": {
    "text": "خوب و ارزان"
  }
}

اگر پرس‌وجو چند کلمه داشته باشد، این شرط فقط زمانی ارضا می‌شود که تمام کلمات در متن ظاهر شوند.

دامنه

{
  "key": "price",
  "range": {
    "gt": null,
    "gte": 100.0,
    "lt": null,
    "lte": 450.0
  }
}

شرط range محدوده‌ی ممکن برای مقادیر مخزن را تعیین می‌کند. اگر چندین مقدار ذخیره شده باشد، حداقل یکی از مقادیر باید با شرط مطابقت داشته باشد.

عملیات‌های مقایسه موجود عبارتند از:

  • gt - بزرگتر از
  • gte - بزرگتر یا مساوی با
  • lt - کمتر از
  • lte - کمتر یا مساوی با

این شرط می‌تواند بر روی اعداد اعشاری و مقادیر صحیح اعمال شود.

جعبه مرزی جغرافیایی

{
  "key": "location",
  "geo_bounding_box": {
    "bottom_right": {
      "lat": 52.495862,
      "lon": 13.455868
    },
    "top_left": {
      "lat": 52.520711,
      "lon": 13.403683
    }
  }
}

این شرط location را در داخل مستطیلی با مختصات در پایین سمت راست به‌عنوان bottom_right و مختصات در بالا سمت چپ به‌عنوان top_left مطابقت می‌دهد.

شعاع جغرافیایی

{
  "key": "location",
  "geo_radius": {
    "center": {
      "lat": 52.520711,
      "lon": 13.403683
    },
    "radius": 1000.0
  }
}

این شرط location را در داخل دایره‌ای با مرکز در center و شعاع radius متری مطابقت می‌دهد.

اگر چندین مقدار ذخیره شده باشد، حداقل یکی از مقادیر باید با شرط مطابقت داشته باشد. این شرایط تنها بر روی مقادیری قابل اعمال هستند که با فرمت داده‌های جغرافیایی مطابقت داشته باشند.

تعداد مقادیر

علاوه بر مقایسه مستقیم مقادیر، فیلترینگ می‌تواند بر اساس تعداد مقادیر هم انجام شود.

به عنوان مثال، با داده‌های زیر:

[
  { "id": 1, "name": "محصول A", "comments": ["عالی!", "عالی"] },
  { "id": 2, "name": "محصول B", "comments": ["منصفانه", "بیشتر انتظار داشتم", "خوب"] }
]

می‌توانیم تنها برای آیتم‌هایی با بیش از دو نظر جستجو کنیم:

{
  "key": "comments",
  "values_count": {
    "gt": 2
  }
}

نتیجه‌ی آن به‌این شکل خواهد بود:

[{ "id": 2, "name": "محصول B", "comments": ["منصفانه", "بیشتر انتظار داشتم", "خوب"] }]

اگر مقدار ذخیره شده یک آرایه نباشد، فرض بر آن است که تعداد مقادیر برابر 1 است.

خالی بودن

گاهی اوقات، فیلتر کردن رکوردها که به ارزش‌های خاصی نیازمند نباشند، مفید است. شرط IsEmpty می‌تواند به شما کمک کند تا به این هدف برسید:

{
  "is_empty": {
    "key": "reports"
  }
}

این شرط همه‌ی رکوردها را مطابقت می‌دهد که فیلد reports در آن وجود نداشته باشد یا مقدار null یا [] را داشته باشد.

IsEmpty به‌طور معمول وقتی استفاده می‌شود که به همراه منفی منطقی must_not استفاده شود، در این صورت همه‌ی مقادیر غیر‌خالی را انتخاب خواهد کرد.

نال بودن

شرط match قادر به آزمون برای مقادیری که NULL هستند نمی‌باشد. باید از شرط IsNull استفاده کنیم:

{
    "is_null": {
        "key": "reports"
    }
}

این شرط همه‌ی رکوردها را مطابقت می‌دهد که فیلد reports وجود داشته باشد و مقداری برابر با NULL داشته باشد.

دارای آی‌دی

این نوع پرس و جو رابطه‌ای با بارهای ذخیره‌شده ندارد، اما در مواقع خاصی بسیار مفید است. به عنوان مثال، کاربران ممکن است بخواهند نتایج جستجو را به عنوان غیرمرتبط علامت گذاری کنند، یا ممکن است بخواهیم فقط بین نقاط خاص جستجو کنیم.

POST /collections/{collection_name}/points/scroll

{
    "filter": {
        "must": [
            { "has_id": [1,3,5,7,9,11] }
        ]
    }
  ...
}

نقاط فیلتر شده به‌این شکل خواهند بود:

[
  { "id": 1, "city": "لندن", "color": "سبز" },
  { "id": 3, "city": "لندن", "color": "آبی" },
  { "id": 5, "city": "مسکو", "color": "سبز" }
]