Filter
Dengan Qdrant, Anda dapat menetapkan kondisi untuk mencari atau mengambil titik, yang berarti Anda dapat menyaring berdasarkan atribut selain dari pencarian kesamaan untuk vektor, mirip dengan menetapkan kondisi SQL where
. Sebagai contoh, Anda dapat menetapkan kondisi untuk payload dan id
dari titik.
Penting untuk menetapkan kondisi tambahan ketika tidak semua fitur dari suatu objek dapat diekspresikan dalam penyisipan. Sebagai contoh, berbagai kebutuhan bisnis seperti ketersediaan inventaris, lokasi pengguna, atau rentang harga yang diharapkan.
Kondisi Filter
Qdrant memungkinkan Anda untuk menggabungkan kondisi dalam klausa. Klausa adalah berbagai operasi logis, seperti OR
, AND
, dan NOT
. Klausa dapat bersarang secara rekursif di dalam satu sama lain, sehingga Anda dapat membuat kembali ekspresi boolean apa pun.
Mari kita lihat klausa yang diimplementasikan dalam Qdrant.
Misalkan kita memiliki kumpulan titik dengan 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" }
]
Harus
Contoh:
POST /collections/{collection_name}/points/scroll
{
"filter": {
"must": [
{ "key": "city", "match": { "value": "London" } },
{ "key": "color", "match": { "value": "red" } }
]
}
...
}
Titik yang difilter akan menjadi:
[{ "id": 2, "city": "London", "color": "red" }]
Ketika menggunakan must
, klausa adalah true
hanya jika setiap kondisi yang tercantum dalam must
dipenuhi. Dalam hal ini, must
setara dengan operator AND
.
Harus
Should
mirip dengan operator OR
dalam SQL.
Contoh:
POST /collections/{collection_name}/points/scroll
{
"filter": {
"should": [
{ "key": "city", "match": { "value": "London" } },
{ "key": "color", "match": { "value": "red" } }
]
}
...
}
Titik yang difilter akan menjadi:
[
{ "id": 1, "city": "London", "color": "green" },
{ "id": 2, "city": "London", "color": "red" },
{ "id": 3, "city": "London", "color": "blue" },
{ "id": 4, "city": "Berlin", "color": "red" }
]
Ketika menggunakan should
, klausa adalah true
selama setidaknya satu kondisi yang tercantum dalam should
dipenuhi. Dalam hal ini, should
setara dengan operator OR
.
must_not
Contoh:
POST /collections/{collection_name}/points/scroll
{
"filter": {
"must_not": [
{ "key": "city", "match": { "value": "London" } },
{ "key": "color", "match": { "value": "red" } }
]
}
...
}
Titik yang difilter akan menjadi:
[
{ "id": 5, "city": "Moscow", "color": "green" },
{ "id": 6, "city": "Moscow", "color": "blue" }
]
Ketika menggunakan must_not
, subklausa adalah true
hanya jika tidak ada dari kondisi yang tercantum dalam must_not
yang terpenuhi. Dalam hal ini, must_not
setara dengan ekspresi (NOT A) AND (NOT B) AND (NOT C)
.
Kombinasi Kondisi
Menggunakan beberapa kondisi secara bersamaan memungkinkan:
POST /collections/{collection_name}/points/scroll
{
"filter": {
"must": [
{ "key": "city", "match": { "value": "London" } }
],
"must_not": [
{ "key": "color", "match": { "value": "red" } }
]
}
...
}
Titik yang difilter akan menjadi:
[
{ "id": 1, "city": "London", "color": "green" },
{ "id": 3, "city": "London", "color": "blue" }
]
Dalam kasus ini, kondisi dikombinasikan menggunakan AND
.
Selain itu, kondisi dapat bersarang secara rekursif. Sebagai contoh:
POST /collections/{collection_name}/points/scroll
{
"filter": {
"must_not": [
{
"must": [
{ "key": "city", "match": { "value": "London" } },
{ "key": "color", "match": { "value": "red" } }
]
}
]
}
...
}
Titik yang difilter akan menjadi:
[
{ "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" }
]
Penyaringan Kondisi
Dalam payload, berbagai jenis nilai sesuai dengan berbagai jenis query yang dapat diterapkan pada mereka. Mari kita lihat varian kondisi yang ada dan jenis data yang mereka terapkan.
Pencocokan
{
"key": "color",
"match": {
"value": "red"
}
}
Untuk jenis lain, kondisi pencocokan terlihat sama persis, hanya dengan penggunaan tipe yang berbeda:
{
"key": "count",
"match": {
"value": 0
}
}
Kondisi paling sederhana memeriksa apakah nilai yang disimpan sama dengan nilai yang diberikan. Jika beberapa nilai disimpan, setidaknya satu di antaranya harus memenuhi kondisi tersebut. Ini dapat diterapkan pada payload kata kunci, bilangan bulat, dan boolean.
Cocok Apapun
Tersedia sejak v1.1.0
Jika Anda ingin memeriksa apakah nilai yang disimpan adalah salah satu dari beberapa nilai, Anda dapat menggunakan kondisi cocok apapun. Cocok apapun memperlakukan nilai yang diberikan sebagai operasi OR logis. Ini juga dapat dijelaskan sebagai operator IN
.
Anda dapat menerapkannya pada payload kata kunci dan bilangan bulat.
Contoh:
{
"key": "color",
"match": {
"any": ["black", "yellow"]
}
}
Dalam contoh ini, jika nilai yang disimpan adalah hitam
atau kuning
, maka kondisi akan terpenuhi.
Jika nilai yang disimpan adalah sebuah array, setidaknya harus ada satu nilai yang cocok dengan salah satu dari nilai yang diberikan. Sebagai contoh, jika nilai yang disimpan adalah ["hitam", "hijau"]
, maka kondisi akan terpenuhi karena "hitam"
ada di ["hitam", "kuning"]
.
Cocok Kecuali
Tersedia sejak v1.2.0
Jika Anda ingin memeriksa apakah nilai yang disimpan bukanlah salah satu dari beberapa nilai, Anda dapat menggunakan kondisi cocok kecuali. Cocok kecuali memperlakukan nilai yang diberikan sebagai operasi NOR logis. Ini juga dapat dijelaskan sebagai operator NOT IN
.
Anda dapat menerapkannya pada payload kata kunci dan bilangan bulat.
Contoh:
{
"key": "color",
"match": {
"except": ["hitam", "kuning"]
}
}
Dalam contoh ini, jika nilai yang disimpan bukanlah hitam
maupun kuning
, maka kondisi akan terpenuhi.
Jika nilai yang disimpan adalah sebuah array, setidaknya harus ada satu nilai yang tidak cocok dengan salah satu dari nilai yang diberikan. Sebagai contoh, jika nilai yang disimpan adalah ["hitam", "hijau"]
, maka kondisi akan terpenuhi karena "hijau"
tidak cocok dengan "hitam"
maupun "kuning"
.
Kunci Bertingkat
Tersedia mulai dari v1.1.0 ke atas
Karena muatan adalah objek JSON sembarang, mungkin Anda perlu menyaring bidang-bidang bertingkat.
Untuk kemudahan, kami menggunakan sintaks yang mirip dengan proyek Jq.
Misalnya, kita memiliki set titik dengan muatan berikut:
[
{
"id": 1,
"country": {
"name": "Jerman",
"cities": [
{
"name": "Berlin",
"population": 3.7,
"sightseeing": ["Gerbang Brandenburg", "Reichstag"]
},
{
"name": "Munich",
"population": 1.5,
"sightseeing": ["Marienplatz", "Taman Olimpiade"]
}
]
}
},
{
"id": 2,
"country": {
"name": "Jepang",
"cities": [
{
"name": "Tokyo",
"population": 9.3,
"sightseeing": ["Menara Tokyo", "Tokyo Skytree"]
},
{
"name": "Osaka",
"population": 2.7,
"sightseeing": ["Osaka Castle", "Universal Studios Japan"]
}
]
}
}
]
Anda dapat menggunakan notasi titik untuk mencari bidang-bidang bertingkat.
POST /collections/{collection_name}/points/scroll
{
"filter": {
"should": [
{
"key": "country.name",
"match": {
"value": "Jerman"
}
}
]
}
}
Anda juga dapat menggunakan sintaks [ ]
untuk mencari array dengan memproyeksikan nilai-nilai dalamnya.
POST /collections/{collection_name}/points/scroll
{
"filter": {
"should": [
{
"key": "country.cities[].population",
"range": {
"gte": 9.0,
}
}
]
}
}
Kueri ini hanya menghasilkan titik dengan id 2, karena hanya Jepang memiliki kota dengan populasi lebih dari 9.0.
Bidang-bidang bertingkat juga bisa berupa array.
POST /collections/{collection_name}/points/scroll
{
"filter": {
"should": [
{
"key": "country.cities[].sightseeing",
"match": {
"value": "Osaka Castle"
}
}
]
}
}
Kueri ini hanya menghasilkan titik dengan id 2, karena hanya Jepang memiliki kota dengan tempat wisata yang mencakup "Osaka Castle".
Filtering Objek Bersarang
Tersedia sejak versi 1.2.0
Secara default, kondisi mengambil seluruh muatan dari sebuah titik ke dalam pertimbangan.
Sebagai contoh, dengan dua titik dalam muatan di bawah ini:
[
{
"id": 1,
"dinosaur": "t-rex",
"diet": [
{ "food": "daun", "likes": false},
{ "food": "daging", "likes": true}
]
},
{
"id": 2,
"dinosaur": "diplodocus",
"diet": [
{ "food": "daun", "likes": true},
{ "food": "daging", "likes": false}
]
}
]
Permintaan berikut akan cocok dengan kedua titik ini:
POST /koleksi/{nama_koleksi}/titik/gulir
{
"filter": {
"must": [
{
"key": "diet[].food",
"match": {
"value": "daging"
}
},
{
"key": "diet[].likes",
"match": {
"value": true
}
}
]
}
}
Alasan kedua titik di atas cocok adalah karena keduanya memenuhi dua kondisi ini:
- "t-rex" memenuhi
diet[1].food
dengan food = daging dandiet[1].likes
dengan likes = true - "diplodocus" memenuhi
diet[1].food
dengan food = daging dandiet[0].likes
dengan likes = true
Untuk hanya mendapatkan titik yang cocok dengan kondisi untuk elemen array, misalnya titik dengan id 1 dalam contoh ini, Anda perlu menggunakan filter objek bersarang.
Filter objek bersarang memungkinkan pengajuan kueri array objek secara independen.
Ini dapat dicapai dengan menggunakan jenis kondisi nested
, yang terdiri dari kunci muatan yang menarik dan filter yang akan diterapkan.
Kunci seharusnya menunjuk ke array objek dan secara opsional dapat menggunakan notasi kurung siku ("data" atau "data[]").
POST /koleksi/{nama_koleksi}/titik/gulir
{
"filter": {
"must": [
"nested": {
{
"key": "diet",
"filter": {
"must": [
{
"key": "food",
"match": {
"value": "daging"
}
},
{
"key": "likes",
"match": {
"value": true
}
}
]
}
}
}
]
}
}
Logika kecocokan diubah untuk diterapkan pada level elemen array di dalam muatan.
Filter bersarang berfungsi dengan cara yang sama seperti saat menerapkan filter bersarang ke satu elemen array. Selama setidaknya satu elemen array cocok dengan filter bersarang, dokumen induk dianggap cocok dengan kondisi.
Keterbatasan
Filter objek bersarang tidak mendukung kondisi has_id
. Jika Anda perlu menggunakannya, letakkan dalam klausa must
yang berdekatan.
POST /koleksi/{nama_koleksi}/titik/gulir
{
"filter": {
"must": [
"nested": {
{
"key": "diet",
"filter": {
"must": [
{
"key": "food",
"match": {
"value": "daging"
}
},
{
"key": "likes",
"match": {
"value": true
}
}
]
}
}
},
{ "has_id": [1] }
]
}
}
Pencocokan Teks Tepat
Tersedia sejak versi 0.10.0
Kasus khusus dari kondisi pencocokan match
adalah kondisi pencocokan text
. Ini memungkinkan Anda untuk mencari substrings, token, atau frasa tertentu dalam bidang teks.
Teks tepat yang memenuhi kondisi ini bergantung pada konfigurasi indeks teks penuh. Konfigurasi ditentukan saat indeks dibuat dan dijelaskan dalam indeks teks penuh.
Jika bidang tidak memiliki indeks teks penuh, kondisi ini akan bekerja berdasarkan pencocokan substring yang tepat.
{
"key": "description",
"match": {
"text": "bagus dan murah"
}
}
Jika kueri memiliki beberapa kata, kondisi ini hanya akan memenuhi syarat ketika semua kata muncul dalam teks.
Rentang
{
"key": "price",
"range": {
"gt": null,
"gte": 100.0,
"lt": null,
"lte": 450.0
}
}
Kondisi range
menetapkan rentang nilai yang mungkin untuk muatan yang disimpan. Jika terdapat beberapa nilai yang disimpan, setidaknya satu nilai harus cocok dengan kondisi tersebut.
Operasi perbandingan yang tersedia mencakup:
-
gt
- lebih besar dari -
gte
- lebih besar dari atau sama dengan -
lt
- kurang dari -
lte
- kurang dari atau sama dengan
Ini dapat diterapkan pada angka desimal dan muatan bilangan bulat.
Kotak Batas Geografis
{
"key": "location",
"geo_bounding_box": {
"bottom_right": {
"lat": 52.495862,
"lon": 13.455868
},
"top_left": {
"lat": 52.520711,
"lon": 13.403683
}
}
}
Ini cocok dengan location
dalam persegi panjang dengan koordinat di bagian kanan bawah sebagai bottom_right
dan koordinat di bagian kiri atas sebagai top_left
.
Radius Geografis
{
"key": "location",
"geo_radius": {
"center": {
"lat": 52.520711,
"lon": 13.403683
},
"radius": 1000.0
}
}
Ini cocok dengan location
dalam lingkaran dengan pusat di center
dan radius radius
meter.
Jika terdapat beberapa nilai yang disimpan, setidaknya satu nilai harus cocok dengan kondisi tersebut. Kondisi-kondisi ini hanya dapat diterapkan pada muatan yang sesuai dengan format data geografis.
Jumlah Nilai
Selain perbandingan nilai langsung, penyaringan juga dapat didasarkan pada jumlah nilai.
Sebagai contoh, diberikan data berikut:
[
{ "id": 1, "name": "Produk A", "comments": ["Sangat baik!", "Luar biasa"] },
{ "id": 2, "name": "Produk B", "comments": ["Cukup baik", "Mengharapkan lebih", "Bagus"] }
]
Kita dapat mencari hanya item dengan lebih dari dua komentar:
{
"key": "comments",
"values_count": {
"gt": 2
}
}
Hasilnya akan menjadi:
[{ "id": 2, "name": "Produk B", "comments": ["Cukup baik", "Mengharapkan lebih", "Bagus"] }]
Jika nilai yang disimpan bukanlah sebuah array, diasumsikan bahwa jumlah nilai sama dengan 1.
Kosong
Terkadang, berguna untuk menyaring catatan yang tidak memiliki nilai tertentu. Kondisi IsEmpty
dapat membantu Anda mencapai hal ini:
{
"is_empty": {
"key": "laporan"
}
}
Kondisi ini akan cocok dengan semua catatan di mana bidang laporan
tidak ada atau memiliki nilai null
atau []
.
IsEmpty seringkali sangat berguna saat digunakan bersamaan dengan negasi logis must_not. Dalam hal ini, ini akan memilih semua nilai non-kosong.
Null
Kondisi match tidak dapat menguji nilai NULL
. Kita harus menggunakan kondisi IsNull
:
{
"is_null": {
"key": "laporan"
}
}
Kondisi ini akan cocok dengan semua catatan di mana bidang laporan
ada dan memiliki nilai NULL
.
Memiliki ID
Jenis kueri ini tidak berkaitan dengan muatan, tetapi sangat berguna dalam situasi tertentu. Misalnya, pengguna mungkin ingin menandai hasil pencarian tertentu sebagai tidak relevan, atau kita mungkin hanya ingin mencari antara titik-titik spesifik.
POST /koleksi/{nama_koleksi}/titik/scroll
{
"filter": {
"must": [
{ "has_id": [1,3,5,7,9,11] }
]
}
...
}
Titik-titik yang disaring akan menjadi:
[
{ "id": 1, "kota": "London", "warna": "hijau" },
{ "id": 3, "kota": "London", "warna": "biru" },
{ "id": 5, "kota": "Moskow", "warna": "hijau" }
]