ตัวกรอง
ด้วย Qdrant คุณสามารถกำหนดเงื่อนไขสำหรับการค้นหาหรือการเรียกรับจุด ซึ่งหมายความว่าคุณสามารถกรองตามแอตทริบิวต์นอกเหนือจากการค้นหาความคล้ายคลึงสำหรับเวกเตอร์ คล้ายกับการกำหนดเงื่อนไข SQL where
ตัวอย่างเช่น คุณสามารถกำหนดเงื่อนไขสำหรับพล็อตที่ payload
และ id
สำคัญที่จะกำหนดเงื่อนไขเพิ่มเติมเมื่อไม่สามารถแสดงถึงคุณสมบัติของวัตถุทั้งหมดได้ในการฝังเข็ม เช่น ความต้องการทางธุรกิจต่าง ๆ เช่น ความพร้อมในสต็อก ที่ตั้งของผู้ใช้ หรือช่วงราคาที่คาดหวัง
เงื่อนไขตัวกรอง
Qdrant อนุญาตให้คุณรวมเงื่อนไขในคลอส คลอสเป็นการดำเนินการตรรกะทางตรรกะคล้ายกับ OR
, AND
, และ NOT
คลอสสามารถถูกซ้อนกันแบบแบบที่ต่างกัน เพื่อนำกลับมาให้อยู่ในนิพจน์บูลีนที่แตกต่างได้
มาดูวิธีการใช้คลอสที่ถูกนำมาใช้ใน Qdrant กัน
สมมติว่าเรามีชุดของพล็อตพร้อมด้วย payload
:
[
{ "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/{collection_name}/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
ควร
ควร
คล้ายกับตัวดำเนินการ OR
ใน SQL
ตัวอย่าง:
POST /collections/{collection_name}/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
, คลอสจะเป็น true
ตลอดเวลาเมื่ออย่างน้อยหนึ่งเงื่อนไขที่ระบุใน should
ถูกทำอย่างเต็มที่ ในทางนี้ should
เทียบเท่ากับตัวดำเนินการ OR
ต้องไม่
ตัวอย่าง:
POST /collections/{collection_name}/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": "London" } }
],
"must_not": [
{ "key": "color", "match": { "value": "red" } }
]
}
...
}
จุดที่ได้กรองแล้วจะเป็นดังนี้:
[
{ "id": 1, "city": "London", "color": "green" },
{ "id": 3, "city": "London", "color": "blue" }
]
ในกรณีนี้เงื่อนไขถูกผสานด้วย AND
.
นอกจากนี้ เงื่อนไขสามารถถูกซ้อนกันได้โดยเรียกตัวเองอีกครั้ง เช่น:
POST /collections/{collection_name}/points/scroll
{
"filter": {
"must_not": [
{
"must": [
{ "key": "city", "match": { "value": "London" } },
{ "key": "color", "match": { "value": "red" } }
]
}
]
}
...
}
จุดที่กรองแล้วจะเป็นดังนี้:
[
{ "id": 1, "city": "London", "color": "green" },
{ "id": 3, "city": "London", "color": "blue" },
{ "id": 4, "city": "Berlin", "color": "red" },
{ "id": 5, "city": "Moscow", "color": "green" },
{ "id": 6, "city": "Moscow", "color": "blue" }
]
การกรองเงื่อนไข
ในข้อมูลส่ง, ค่าประเภทต่างๆที่ประกอบด้วยชนิดของการค้นหาที่สามารถนำไปปรับใช้ได้. ขอดูตัวอย่างเงื่อนไขต่างๆและชนิดข้อมูลที่มันนำไปใช้
การจับคู่
{
"key": "color",
"match": {
"value": "red"
}
}
สำหรับชนิดอื่นๆ เงื่อนไขการจับคู่ดูเหมือนกันทุกประการ แค่เพียงแต่ใช้ชนิดที่ต่างกัน:
{
"key": "count",
"match": {
"value": 0
}
}
การตรวจสอบเงื่อนไขที่ง่ายที่สุดคือการตรวจสอบว่าค่าที่จัดเก็บเท่ากับค่าที่กำหนด. หากมีการจัดเก็บค่าหลายค่า อย่างน้อยหนึ่งค่าต้องเป็นไปตามเงื่อนไข. นี้สามารถนำไปปรับใช้กับ payload ช่องคำสำคัญ, ตัวเลข, และค่าบูลีน
การจับคู่ใดๆ
ใช้ได้ตั้งแต่ v1.1.0
หากต้องการตรวจสอบว่าค่าที่จัดเก็บเป็นหนึ่งในค่าหลายๆค่า คุณสามารถใช้การจับคู่ใดๆ. การจับคู่ใดๆจะจับคู่ค่าที่กำหนดเป็นการดำเนินการ OR
ตรรกะ. มันยังสามารถอธิบายได้ว่าเป็นตัวดำเนินการ IN
คุณสามารถนำไปปรับใช้กับ payload ชุดคำสำคัญ และ เลขจำนวนเต็ม
ตัวอย่าง:
{
"key": "color",
"match": {
"any": ["black", "yellow"]
}
}
ในตัวอย่างนี้ หากค่าที่จัดเก็บเป็น black
หรือ yellow
แล้วเงื่อนไขจะถูกพอใจ
หากค่าที่จัดเก็บเป็นอาร์เรย์, จะต้องมีอย่างน้อยหนึ่งค่าที่ตรงกับค่าที่กำหนด ยกตัวอย่างเช่น หากค่าที่จัดเก็บเป็น ["black", "green"]
, แล้วเงื่อนไขจะถูกพอใจเพราะ "black"
อยู่ใน ["black", "yellow"]
.
การจับคู่ที่ยกเว้น
ใช้ได้ตั้งแต่ v1.2.0
หากต้องการตรวจสอบว่าค่าที่ถูกจัดเก็บไม่ใช่หนึ่งในค่าหลายๆค่า คุณสามารถใช้การจับคู่ที่ยกเว้น. การจับคู่ที่ยกเว้นจะจับคู่ค่าที่กำหนดเป็นการดำเนินการ NOR
ตรรกะ. มันยังสามารถอธิบายได้ว่าเป็นตัวดำเนินการ NOT IN
คุณสามารถนำไปปรับใช้กับ payload ชุดคำสำคัญ และ เลขจำนวนเต็ม
ตัวอย่าง:
{
"key": "color",
"match": {
"except": ["black", "yellow"]
}
}
ในตัวอย่างนี้ หากค่าที่ถูกจัดเก็บไม่ใช่ black
และไม่ใช่ yellow
แล้วเงื่อนไขจะถูกพอใจ
หากค่าที่ถูกจัดเก็บเป็นอาร์เรย์, จะต้องมีค่าที่อย่างน้อยหนึ่งค่าที่ไม่ตรงกับค่าที่กำหนด ยกตัวอย่างเช่น, หากค่าที่ถูกจัดเก็บเป็น ["black", "green"]
, แล้วเงื่อนไขจะถูกพอใจเพราะ "green"
ไม่ตรงกับ "black"
หรือ "yellow"
.
คีย์ที่ซ้อนกัน
สามารถใช้ได้ตั้งแต่ 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/{collection_name}/points/scroll
{
"filter": {
"should": [
{
"key": "country.name",
"match": {
"value": "เยอรมนี"
}
}
]
}
}
คุณยังสามารถใช้ไวยากรณ์ [ ]
เพื่อค้นหาอาร์เรย์โดยการสร้างค่าภายใน
POST /collections/{collection_name}/points/scroll
{
"filter": {
"should": [
{
"key": "country.cities[].population",
"range": {
"gte": 9.0,
}
}
]
}
}
คิวรี่นี้จะแสดงเฉพาะจุดที่มี id คือ 2 เนื่องจากเฉพาะประเทศญี่ปุ่นมีเมืองที่มีประชากรมากกว่า 9.0
ฟิลด์ที่ซ้อนกันยังอาจเป็นอาร์เรย์
POST /collections/{collection_name}/points/scroll
{
"filter": {
"should": [
{
"key": "country.cities[].sightseeing",
"match": {
"value": "ปราสาทโอซาก้า"
}
}
]
}
}
คิวรี่นี้จะแสดงเฉพาะจุดที่มี id คือ 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
พร้อมอาหาร = เนื้อ และdiet[1].likes
กับ likes = true - "diplodocus" ตรงกับ
diet[1].food
พร้อมอาหาร = เนื้อ และdiet[0].likes
กับ likes = true
หากต้องการรับเพียงพอยต์ที่ตรงกับเงื่อนไขสำหรับอาร์เรย์องค์ประกอบ ตัวอย่างเช่น พอยต์ที่มี id 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
ไม่มีอยู่หรือมีค่าเป็น null
หรือ []
IsEmpty มักจะมีประโยชน์มากเมื่อใช้ร่วมกับการปฏิเสธทางตรรกะ must_not ในกรณีนี้ มันจะเลือกทุกค่าที่ไม่ว่างเปล่า
เป็นค่าว่าง
เงื่อนไข match ไม่สามารถทดสอบค่า NULL
ได้ จะต้องใช้เงื่อนไข IsNull
:
{
"is_null": {
"key": "รายงาน"
}
}
เงื่อนไขนี้จะตรงกับบันทึกทั้งหมดที่ฟิลด์ reports
มีอยู่และมีค่าเป็น NULL
มี ID
ประเภทการค้นหานี้ไม่เกี่ยวข้องกับข้อมูลที่เก็บไว้ แต่มันมีประโยชน์มากในบางสถานการณ์ เช่น ผู้ใช้อาจต้องการติดแท็กผลลัพธ์ค้นหาบางอย่างว่าไม่เกี่ยวข้อง หรือเราอาจต้องการค้นหาระหว่างจุดที่แน่นอน
POST /collections/{collection_name}/points/scroll
{
"filter": {
"must": [
{ "has_id": [1,3,5,7,9,11] }
]
}
...
}
จะได้ผลลัพธ์ที่กรองมาว่า:
[
{ "id": 1, "city": "ลอนดอน", "สี": "เขียว" },
{ "id": 3, "city": "ลอนดอน", "สี": "น้ำเงิน" },
{ "id": 5, "city": "มอสโก", "สี": "เขียว" }
]