chub-dev 0.1.0 → 0.1.2-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -0
- package/bin/chub-mcp +2 -0
- package/dist/airtable/docs/database/javascript/DOC.md +1437 -0
- package/dist/airtable/docs/database/python/DOC.md +1735 -0
- package/dist/amplitude/docs/analytics/javascript/DOC.md +1282 -0
- package/dist/amplitude/docs/analytics/python/DOC.md +1199 -0
- package/dist/anthropic/docs/claude-api/javascript/DOC.md +503 -0
- package/dist/anthropic/docs/claude-api/python/DOC.md +389 -0
- package/dist/asana/docs/tasks/DOC.md +1396 -0
- package/dist/assemblyai/docs/transcription/DOC.md +1043 -0
- package/dist/atlassian/docs/confluence/javascript/DOC.md +1347 -0
- package/dist/atlassian/docs/confluence/python/DOC.md +1604 -0
- package/dist/auth0/docs/identity/javascript/DOC.md +968 -0
- package/dist/auth0/docs/identity/python/DOC.md +1199 -0
- package/dist/aws/docs/s3/javascript/DOC.md +1773 -0
- package/dist/aws/docs/s3/python/DOC.md +1807 -0
- package/dist/binance/docs/trading/javascript/DOC.md +1315 -0
- package/dist/binance/docs/trading/python/DOC.md +1454 -0
- package/dist/braintree/docs/gateway/javascript/DOC.md +1278 -0
- package/dist/braintree/docs/gateway/python/DOC.md +1179 -0
- package/dist/chromadb/docs/embeddings-db/javascript/DOC.md +1263 -0
- package/dist/chromadb/docs/embeddings-db/python/DOC.md +1707 -0
- package/dist/clerk/docs/auth/javascript/DOC.md +1220 -0
- package/dist/clerk/docs/auth/python/DOC.md +274 -0
- package/dist/cloudflare/docs/workers/javascript/DOC.md +918 -0
- package/dist/cloudflare/docs/workers/python/DOC.md +994 -0
- package/dist/cockroachdb/docs/distributed-db/DOC.md +1500 -0
- package/dist/cohere/docs/llm/DOC.md +1335 -0
- package/dist/datadog/docs/monitoring/javascript/DOC.md +1740 -0
- package/dist/datadog/docs/monitoring/python/DOC.md +1815 -0
- package/dist/deepgram/docs/speech/javascript/DOC.md +885 -0
- package/dist/deepgram/docs/speech/python/DOC.md +685 -0
- package/dist/deepl/docs/translation/javascript/DOC.md +887 -0
- package/dist/deepl/docs/translation/python/DOC.md +944 -0
- package/dist/deepseek/docs/llm/DOC.md +1220 -0
- package/dist/directus/docs/headless-cms/javascript/DOC.md +1128 -0
- package/dist/directus/docs/headless-cms/python/DOC.md +1276 -0
- package/dist/discord/docs/bot/javascript/DOC.md +1090 -0
- package/dist/discord/docs/bot/python/DOC.md +1130 -0
- package/dist/elasticsearch/docs/search/DOC.md +1634 -0
- package/dist/elevenlabs/docs/text-to-speech/javascript/DOC.md +336 -0
- package/dist/elevenlabs/docs/text-to-speech/python/DOC.md +552 -0
- package/dist/firebase/docs/auth/DOC.md +1015 -0
- package/dist/gemini/docs/genai/javascript/DOC.md +691 -0
- package/dist/gemini/docs/genai/python/DOC.md +555 -0
- package/dist/github/docs/octokit/DOC.md +1560 -0
- package/dist/google/docs/bigquery/javascript/DOC.md +1688 -0
- package/dist/google/docs/bigquery/python/DOC.md +1503 -0
- package/dist/hubspot/docs/crm/javascript/DOC.md +1805 -0
- package/dist/hubspot/docs/crm/python/DOC.md +2033 -0
- package/dist/huggingface/docs/transformers/DOC.md +948 -0
- package/dist/intercom/docs/messaging/javascript/DOC.md +1844 -0
- package/dist/intercom/docs/messaging/python/DOC.md +1797 -0
- package/dist/jira/docs/issues/javascript/DOC.md +1420 -0
- package/dist/jira/docs/issues/python/DOC.md +1492 -0
- package/dist/kafka/docs/streaming/javascript/DOC.md +1671 -0
- package/dist/kafka/docs/streaming/python/DOC.md +1464 -0
- package/dist/landingai-ade/docs/api/DOC.md +620 -0
- package/dist/landingai-ade/docs/sdk/python/DOC.md +489 -0
- package/dist/landingai-ade/docs/sdk/typescript/DOC.md +542 -0
- package/dist/landingai-ade/skills/SKILL.md +489 -0
- package/dist/launchdarkly/docs/feature-flags/javascript/DOC.md +1191 -0
- package/dist/launchdarkly/docs/feature-flags/python/DOC.md +1671 -0
- package/dist/linear/docs/tracker/DOC.md +1554 -0
- package/dist/livekit/docs/realtime/javascript/DOC.md +303 -0
- package/dist/livekit/docs/realtime/python/DOC.md +163 -0
- package/dist/mailchimp/docs/marketing/DOC.md +1420 -0
- package/dist/meilisearch/docs/search/DOC.md +1241 -0
- package/dist/microsoft/docs/onedrive/javascript/DOC.md +1421 -0
- package/dist/microsoft/docs/onedrive/python/DOC.md +1549 -0
- package/dist/mongodb/docs/atlas/DOC.md +2041 -0
- package/dist/notion/docs/workspace-api/javascript/DOC.md +1435 -0
- package/dist/notion/docs/workspace-api/python/DOC.md +1400 -0
- package/dist/okta/docs/identity/javascript/DOC.md +1171 -0
- package/dist/okta/docs/identity/python/DOC.md +1401 -0
- package/dist/openai/docs/chat/javascript/DOC.md +407 -0
- package/dist/openai/docs/chat/python/DOC.md +568 -0
- package/dist/paypal/docs/checkout/DOC.md +278 -0
- package/dist/pinecone/docs/sdk/javascript/DOC.md +984 -0
- package/dist/pinecone/docs/sdk/python/DOC.md +1395 -0
- package/dist/plaid/docs/banking/javascript/DOC.md +1163 -0
- package/dist/plaid/docs/banking/python/DOC.md +1203 -0
- package/dist/playwright-community/skills/login-flows/SKILL.md +108 -0
- package/dist/postmark/docs/transactional-email/DOC.md +1168 -0
- package/dist/prisma/docs/orm/javascript/DOC.md +1419 -0
- package/dist/prisma/docs/orm/python/DOC.md +1317 -0
- package/dist/qdrant/docs/vector-search/javascript/DOC.md +1221 -0
- package/dist/qdrant/docs/vector-search/python/DOC.md +1653 -0
- package/dist/rabbitmq/docs/message-queue/javascript/DOC.md +1193 -0
- package/dist/rabbitmq/docs/message-queue/python/DOC.md +1243 -0
- package/dist/razorpay/docs/payments/javascript/DOC.md +1219 -0
- package/dist/razorpay/docs/payments/python/DOC.md +1330 -0
- package/dist/redis/docs/key-value/javascript/DOC.md +1851 -0
- package/dist/redis/docs/key-value/python/DOC.md +2054 -0
- package/dist/registry.json +2817 -0
- package/dist/replicate/docs/model-hosting/DOC.md +1318 -0
- package/dist/resend/docs/email/DOC.md +1271 -0
- package/dist/salesforce/docs/crm/javascript/DOC.md +1241 -0
- package/dist/salesforce/docs/crm/python/DOC.md +1183 -0
- package/dist/search-index.json +1 -0
- package/dist/sendgrid/docs/email-api/javascript/DOC.md +371 -0
- package/dist/sendgrid/docs/email-api/python/DOC.md +656 -0
- package/dist/sentry/docs/error-tracking/javascript/DOC.md +1073 -0
- package/dist/sentry/docs/error-tracking/python/DOC.md +1309 -0
- package/dist/shopify/docs/storefront/DOC.md +457 -0
- package/dist/slack/docs/workspace/javascript/DOC.md +933 -0
- package/dist/slack/docs/workspace/python/DOC.md +271 -0
- package/dist/square/docs/payments/javascript/DOC.md +1855 -0
- package/dist/square/docs/payments/python/DOC.md +1728 -0
- package/dist/stripe/docs/api/DOC.md +1727 -0
- package/dist/stripe/docs/payments/DOC.md +1726 -0
- package/dist/stytch/docs/auth/javascript/DOC.md +1813 -0
- package/dist/stytch/docs/auth/python/DOC.md +1962 -0
- package/dist/supabase/docs/client/DOC.md +1606 -0
- package/dist/twilio/docs/messaging/python/DOC.md +469 -0
- package/dist/twilio/docs/messaging/typescript/DOC.md +946 -0
- package/dist/vercel/docs/platform/DOC.md +1940 -0
- package/dist/weaviate/docs/vector-db/javascript/DOC.md +1268 -0
- package/dist/weaviate/docs/vector-db/python/DOC.md +1388 -0
- package/dist/zendesk/docs/support/javascript/DOC.md +2150 -0
- package/dist/zendesk/docs/support/python/DOC.md +2297 -0
- package/package.json +22 -6
- package/skills/get-api-docs/SKILL.md +84 -0
- package/src/commands/annotate.js +83 -0
- package/src/commands/build.js +12 -1
- package/src/commands/feedback.js +150 -0
- package/src/commands/get.js +83 -42
- package/src/commands/search.js +7 -0
- package/src/index.js +43 -17
- package/src/lib/analytics.js +90 -0
- package/src/lib/annotations.js +57 -0
- package/src/lib/bm25.js +170 -0
- package/src/lib/cache.js +69 -6
- package/src/lib/config.js +8 -3
- package/src/lib/identity.js +99 -0
- package/src/lib/registry.js +103 -20
- package/src/lib/telemetry.js +86 -0
- package/src/mcp/server.js +177 -0
- package/src/mcp/tools.js +251 -0
|
@@ -0,0 +1,1653 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vector-search
|
|
3
|
+
description: "Qdrant Python Client — use qdrant-client for vector database operations in Python"
|
|
4
|
+
metadata:
|
|
5
|
+
languages: "python"
|
|
6
|
+
versions: "1.15.1"
|
|
7
|
+
updated-on: "2026-03-02"
|
|
8
|
+
source: maintainer
|
|
9
|
+
tags: "qdrant,vector-search,embeddings,similarity,ai"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Qdrant Python Client v1.15.1
|
|
13
|
+
|
|
14
|
+
## Golden Rule
|
|
15
|
+
|
|
16
|
+
**Always use `qdrant-client` for Qdrant vector database operations in Python.**
|
|
17
|
+
|
|
18
|
+
Install with:
|
|
19
|
+
```bash
|
|
20
|
+
pip install qdrant-client
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
For FastEmbed integration (automatic embedding generation):
|
|
24
|
+
```bash
|
|
25
|
+
pip install 'qdrant-client[fastembed]'
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Do NOT use:**
|
|
29
|
+
- Outdated or unmaintained Qdrant Python packages
|
|
30
|
+
- Direct REST API calls when the client library provides methods
|
|
31
|
+
|
|
32
|
+
The official `qdrant-client` provides both synchronous and asynchronous interfaces, gRPC support, and built-in FastEmbed integration.
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Basic installation
|
|
38
|
+
pip install qdrant-client
|
|
39
|
+
|
|
40
|
+
# With FastEmbed support
|
|
41
|
+
pip install 'qdrant-client[fastembed]'
|
|
42
|
+
|
|
43
|
+
# Or using uv
|
|
44
|
+
uv pip install qdrant-client
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Initialization
|
|
48
|
+
|
|
49
|
+
### In-Memory Client
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
from qdrant_client import QdrantClient
|
|
53
|
+
|
|
54
|
+
# In-memory instance (no persistence)
|
|
55
|
+
client = QdrantClient(":memory:")
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Local Persistent Storage
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from qdrant_client import QdrantClient
|
|
62
|
+
|
|
63
|
+
# Persistent local storage
|
|
64
|
+
client = QdrantClient(path="./qdrant_data")
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Remote Server
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from qdrant_client import QdrantClient
|
|
71
|
+
|
|
72
|
+
# Connect to Qdrant server
|
|
73
|
+
client = QdrantClient(host="localhost", port=6333)
|
|
74
|
+
|
|
75
|
+
# Alternative using URL
|
|
76
|
+
client = QdrantClient(url="http://localhost:6333")
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Qdrant Cloud
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
from qdrant_client import QdrantClient
|
|
83
|
+
|
|
84
|
+
# Connect to Qdrant Cloud
|
|
85
|
+
client = QdrantClient(
|
|
86
|
+
url="https://xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.us-east-0-1.aws.cloud.qdrant.io",
|
|
87
|
+
api_key="your-api-key-here"
|
|
88
|
+
)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### With Environment Variables
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
import os
|
|
95
|
+
from qdrant_client import QdrantClient
|
|
96
|
+
|
|
97
|
+
client = QdrantClient(
|
|
98
|
+
url=os.getenv("QDRANT_URL", "http://localhost:6333"),
|
|
99
|
+
api_key=os.getenv("QDRANT_API_KEY")
|
|
100
|
+
)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### gRPC Configuration
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from qdrant_client import QdrantClient
|
|
107
|
+
|
|
108
|
+
# Use gRPC for better performance
|
|
109
|
+
client = QdrantClient(
|
|
110
|
+
host="localhost",
|
|
111
|
+
grpc_port=6334,
|
|
112
|
+
prefer_grpc=True
|
|
113
|
+
)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Async Client
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
from qdrant_client import AsyncQdrantClient
|
|
120
|
+
|
|
121
|
+
# Async client initialization
|
|
122
|
+
async_client = AsyncQdrantClient(
|
|
123
|
+
url="http://localhost:6333"
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# Use with async/await
|
|
127
|
+
async def main():
|
|
128
|
+
collections = await async_client.get_collections()
|
|
129
|
+
print(collections)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Collections
|
|
133
|
+
|
|
134
|
+
### List Collections
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
collections = client.get_collections()
|
|
138
|
+
print(collections.collections)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Check Collection Exists
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
exists = client.collection_exists("my_collection")
|
|
145
|
+
print(f"Collection exists: {exists}")
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Create Collection - Single Vector
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
from qdrant_client.models import Distance, VectorParams
|
|
152
|
+
|
|
153
|
+
client.create_collection(
|
|
154
|
+
collection_name="my_collection",
|
|
155
|
+
vectors_config=VectorParams(size=384, distance=Distance.COSINE)
|
|
156
|
+
)
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Distance Metrics
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
from qdrant_client.models import Distance
|
|
163
|
+
|
|
164
|
+
# Available distance metrics:
|
|
165
|
+
# Distance.COSINE - Cosine similarity
|
|
166
|
+
# Distance.EUCLID - Euclidean distance
|
|
167
|
+
# Distance.DOT - Dot product
|
|
168
|
+
# Distance.MANHATTAN - Manhattan distance
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Create Collection - Named Vectors
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
from qdrant_client.models import Distance, VectorParams
|
|
175
|
+
|
|
176
|
+
client.create_collection(
|
|
177
|
+
collection_name="multi_vector_collection",
|
|
178
|
+
vectors_config={
|
|
179
|
+
"image": VectorParams(size=512, distance=Distance.DOT),
|
|
180
|
+
"text": VectorParams(size=384, distance=Distance.COSINE)
|
|
181
|
+
}
|
|
182
|
+
)
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Create Collection - Advanced Configuration
|
|
186
|
+
|
|
187
|
+
```python
|
|
188
|
+
from qdrant_client.models import (
|
|
189
|
+
Distance,
|
|
190
|
+
VectorParams,
|
|
191
|
+
OptimizersConfigDiff,
|
|
192
|
+
HnswConfigDiff,
|
|
193
|
+
QuantizationConfig,
|
|
194
|
+
ScalarQuantization,
|
|
195
|
+
ScalarType
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
client.create_collection(
|
|
199
|
+
collection_name="advanced_collection",
|
|
200
|
+
vectors_config=VectorParams(size=768, distance=Distance.COSINE),
|
|
201
|
+
shard_number=2,
|
|
202
|
+
replication_factor=1,
|
|
203
|
+
write_consistency_factor=1,
|
|
204
|
+
on_disk_payload=True,
|
|
205
|
+
hnsw_config=HnswConfigDiff(
|
|
206
|
+
m=16,
|
|
207
|
+
ef_construct=100,
|
|
208
|
+
full_scan_threshold=10000
|
|
209
|
+
),
|
|
210
|
+
optimizers_config=OptimizersConfigDiff(
|
|
211
|
+
default_segment_number=2,
|
|
212
|
+
indexing_threshold=20000
|
|
213
|
+
),
|
|
214
|
+
quantization_config=ScalarQuantization(
|
|
215
|
+
scalar=ScalarType.INT8,
|
|
216
|
+
quantile=0.99,
|
|
217
|
+
always_ram=True
|
|
218
|
+
)
|
|
219
|
+
)
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Create Collection - Sparse Vectors
|
|
223
|
+
|
|
224
|
+
```python
|
|
225
|
+
from qdrant_client.models import Distance, VectorParams, SparseVectorParams
|
|
226
|
+
|
|
227
|
+
client.create_collection(
|
|
228
|
+
collection_name="sparse_collection",
|
|
229
|
+
vectors_config={
|
|
230
|
+
"dense": VectorParams(size=384, distance=Distance.COSINE),
|
|
231
|
+
"sparse": SparseVectorParams()
|
|
232
|
+
}
|
|
233
|
+
)
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Get Collection Info
|
|
237
|
+
|
|
238
|
+
```python
|
|
239
|
+
info = client.get_collection("my_collection")
|
|
240
|
+
print(f"Points count: {info.points_count}")
|
|
241
|
+
print(f"Vectors config: {info.config.params.vectors}")
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Update Collection
|
|
245
|
+
|
|
246
|
+
```python
|
|
247
|
+
from qdrant_client.models import OptimizersConfigDiff
|
|
248
|
+
|
|
249
|
+
client.update_collection(
|
|
250
|
+
collection_name="my_collection",
|
|
251
|
+
optimizers_config=OptimizersConfigDiff(
|
|
252
|
+
indexing_threshold=30000
|
|
253
|
+
)
|
|
254
|
+
)
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Delete Collection
|
|
258
|
+
|
|
259
|
+
```python
|
|
260
|
+
client.delete_collection("my_collection")
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Points (Vectors)
|
|
264
|
+
|
|
265
|
+
### Upsert Points - Basic
|
|
266
|
+
|
|
267
|
+
```python
|
|
268
|
+
from qdrant_client.models import PointStruct
|
|
269
|
+
|
|
270
|
+
operation_info = client.upsert(
|
|
271
|
+
collection_name="my_collection",
|
|
272
|
+
wait=True,
|
|
273
|
+
points=[
|
|
274
|
+
PointStruct(
|
|
275
|
+
id=1,
|
|
276
|
+
vector=[0.05, 0.61, 0.76, 0.74],
|
|
277
|
+
payload={"city": "Berlin", "price": 1.99}
|
|
278
|
+
),
|
|
279
|
+
PointStruct(
|
|
280
|
+
id=2,
|
|
281
|
+
vector=[0.19, 0.81, 0.75, 0.11],
|
|
282
|
+
payload={"city": "London", "price": 2.49}
|
|
283
|
+
)
|
|
284
|
+
]
|
|
285
|
+
)
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Upsert Points - Auto ID
|
|
289
|
+
|
|
290
|
+
```python
|
|
291
|
+
from qdrant_client.models import PointStruct
|
|
292
|
+
import uuid
|
|
293
|
+
|
|
294
|
+
points = [
|
|
295
|
+
PointStruct(
|
|
296
|
+
id=str(uuid.uuid4()),
|
|
297
|
+
vector=[0.1, 0.2, 0.3, 0.4],
|
|
298
|
+
payload={"title": "Document 1"}
|
|
299
|
+
)
|
|
300
|
+
]
|
|
301
|
+
|
|
302
|
+
client.upsert(
|
|
303
|
+
collection_name="my_collection",
|
|
304
|
+
points=points
|
|
305
|
+
)
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Upsert Points - Named Vectors
|
|
309
|
+
|
|
310
|
+
```python
|
|
311
|
+
from qdrant_client.models import PointStruct
|
|
312
|
+
|
|
313
|
+
client.upsert(
|
|
314
|
+
collection_name="multi_vector_collection",
|
|
315
|
+
points=[
|
|
316
|
+
PointStruct(
|
|
317
|
+
id=1,
|
|
318
|
+
vector={
|
|
319
|
+
"image": [0.1, 0.2, 0.3, 0.4],
|
|
320
|
+
"text": [0.5, 0.6, 0.7, 0.8]
|
|
321
|
+
},
|
|
322
|
+
payload={"title": "Product A", "category": "electronics"}
|
|
323
|
+
)
|
|
324
|
+
]
|
|
325
|
+
)
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### Upsert Points - Sparse Vectors
|
|
329
|
+
|
|
330
|
+
```python
|
|
331
|
+
from qdrant_client.models import PointStruct, SparseVector
|
|
332
|
+
|
|
333
|
+
client.upsert(
|
|
334
|
+
collection_name="sparse_collection",
|
|
335
|
+
points=[
|
|
336
|
+
PointStruct(
|
|
337
|
+
id=1,
|
|
338
|
+
vector={
|
|
339
|
+
"dense": [0.1, 0.2, 0.3, 0.4],
|
|
340
|
+
"sparse": SparseVector(
|
|
341
|
+
indices=[1, 3, 5, 7],
|
|
342
|
+
values=[0.1, 0.2, 0.3, 0.4]
|
|
343
|
+
)
|
|
344
|
+
},
|
|
345
|
+
payload={"text": "Sample document"}
|
|
346
|
+
)
|
|
347
|
+
]
|
|
348
|
+
)
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### Upsert Points - Batch
|
|
352
|
+
|
|
353
|
+
```python
|
|
354
|
+
from qdrant_client.models import PointStruct
|
|
355
|
+
import numpy as np
|
|
356
|
+
|
|
357
|
+
vectors = np.random.rand(1000, 384)
|
|
358
|
+
points = [
|
|
359
|
+
PointStruct(
|
|
360
|
+
id=idx,
|
|
361
|
+
vector=vector.tolist(),
|
|
362
|
+
payload={"index": idx, "category": f"cat_{idx % 10}"}
|
|
363
|
+
)
|
|
364
|
+
for idx, vector in enumerate(vectors)
|
|
365
|
+
]
|
|
366
|
+
|
|
367
|
+
client.upsert(
|
|
368
|
+
collection_name="my_collection",
|
|
369
|
+
points=points,
|
|
370
|
+
wait=True
|
|
371
|
+
)
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Add Documents with FastEmbed
|
|
375
|
+
|
|
376
|
+
```python
|
|
377
|
+
documents = [
|
|
378
|
+
"Qdrant has Langchain integrations",
|
|
379
|
+
"Qdrant also has Llama Index integrations",
|
|
380
|
+
"Qdrant is a vector database"
|
|
381
|
+
]
|
|
382
|
+
|
|
383
|
+
metadata = [
|
|
384
|
+
{"source": "langchain-docs"},
|
|
385
|
+
{"source": "llamaindex-docs"},
|
|
386
|
+
{"source": "qdrant-docs"}
|
|
387
|
+
]
|
|
388
|
+
|
|
389
|
+
ids = [1, 2, 3]
|
|
390
|
+
|
|
391
|
+
client.add(
|
|
392
|
+
collection_name="demo_collection",
|
|
393
|
+
documents=documents,
|
|
394
|
+
metadata=metadata,
|
|
395
|
+
ids=ids
|
|
396
|
+
)
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### Retrieve Points by ID
|
|
400
|
+
|
|
401
|
+
```python
|
|
402
|
+
points = client.retrieve(
|
|
403
|
+
collection_name="my_collection",
|
|
404
|
+
ids=[1, 2, 3],
|
|
405
|
+
with_payload=True,
|
|
406
|
+
with_vectors=False
|
|
407
|
+
)
|
|
408
|
+
|
|
409
|
+
for point in points:
|
|
410
|
+
print(f"ID: {point.id}, Payload: {point.payload}")
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
### Retrieve Points - With Vectors
|
|
414
|
+
|
|
415
|
+
```python
|
|
416
|
+
points = client.retrieve(
|
|
417
|
+
collection_name="my_collection",
|
|
418
|
+
ids=[1, 2, 3],
|
|
419
|
+
with_payload=True,
|
|
420
|
+
with_vectors=True
|
|
421
|
+
)
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### Delete Points by ID
|
|
425
|
+
|
|
426
|
+
```python
|
|
427
|
+
client.delete(
|
|
428
|
+
collection_name="my_collection",
|
|
429
|
+
points_selector=[1, 2, 3]
|
|
430
|
+
)
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### Delete Points by Filter
|
|
434
|
+
|
|
435
|
+
```python
|
|
436
|
+
from qdrant_client.models import Filter, FieldCondition, MatchValue
|
|
437
|
+
|
|
438
|
+
client.delete(
|
|
439
|
+
collection_name="my_collection",
|
|
440
|
+
points_selector=Filter(
|
|
441
|
+
must=[
|
|
442
|
+
FieldCondition(
|
|
443
|
+
key="city",
|
|
444
|
+
match=MatchValue(value="Berlin")
|
|
445
|
+
)
|
|
446
|
+
]
|
|
447
|
+
)
|
|
448
|
+
)
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### Count Points
|
|
452
|
+
|
|
453
|
+
```python
|
|
454
|
+
count = client.count(
|
|
455
|
+
collection_name="my_collection",
|
|
456
|
+
exact=True
|
|
457
|
+
)
|
|
458
|
+
print(f"Total points: {count.count}")
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### Count Points with Filter
|
|
462
|
+
|
|
463
|
+
```python
|
|
464
|
+
from qdrant_client.models import Filter, FieldCondition, Range
|
|
465
|
+
|
|
466
|
+
count = client.count(
|
|
467
|
+
collection_name="my_collection",
|
|
468
|
+
count_filter=Filter(
|
|
469
|
+
must=[
|
|
470
|
+
FieldCondition(
|
|
471
|
+
key="price",
|
|
472
|
+
range=Range(gte=2.0)
|
|
473
|
+
)
|
|
474
|
+
]
|
|
475
|
+
),
|
|
476
|
+
exact=True
|
|
477
|
+
)
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
## Scroll (Pagination)
|
|
481
|
+
|
|
482
|
+
### Basic Scroll
|
|
483
|
+
|
|
484
|
+
```python
|
|
485
|
+
records, next_page_offset = client.scroll(
|
|
486
|
+
collection_name="my_collection",
|
|
487
|
+
limit=10,
|
|
488
|
+
with_payload=True,
|
|
489
|
+
with_vectors=False
|
|
490
|
+
)
|
|
491
|
+
|
|
492
|
+
for record in records:
|
|
493
|
+
print(f"ID: {record.id}, Payload: {record.payload}")
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
### Scroll with Filter
|
|
497
|
+
|
|
498
|
+
```python
|
|
499
|
+
from qdrant_client.models import Filter, FieldCondition, MatchValue
|
|
500
|
+
|
|
501
|
+
records, next_page_offset = client.scroll(
|
|
502
|
+
collection_name="my_collection",
|
|
503
|
+
scroll_filter=Filter(
|
|
504
|
+
must=[
|
|
505
|
+
FieldCondition(
|
|
506
|
+
key="city",
|
|
507
|
+
match=MatchValue(value="Berlin")
|
|
508
|
+
)
|
|
509
|
+
]
|
|
510
|
+
),
|
|
511
|
+
limit=20,
|
|
512
|
+
with_payload=True
|
|
513
|
+
)
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
### Scroll Pagination
|
|
517
|
+
|
|
518
|
+
```python
|
|
519
|
+
offset = None
|
|
520
|
+
all_points = []
|
|
521
|
+
|
|
522
|
+
while True:
|
|
523
|
+
records, next_page_offset = client.scroll(
|
|
524
|
+
collection_name="my_collection",
|
|
525
|
+
limit=100,
|
|
526
|
+
offset=offset,
|
|
527
|
+
with_payload=True,
|
|
528
|
+
with_vectors=False
|
|
529
|
+
)
|
|
530
|
+
|
|
531
|
+
all_points.extend(records)
|
|
532
|
+
|
|
533
|
+
if next_page_offset is None:
|
|
534
|
+
break
|
|
535
|
+
|
|
536
|
+
offset = next_page_offset
|
|
537
|
+
|
|
538
|
+
print(f"Total points retrieved: {len(all_points)}")
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
### Scroll with Order By
|
|
542
|
+
|
|
543
|
+
```python
|
|
544
|
+
records, next_page_offset = client.scroll(
|
|
545
|
+
collection_name="my_collection",
|
|
546
|
+
limit=15,
|
|
547
|
+
order_by="timestamp",
|
|
548
|
+
with_payload=True
|
|
549
|
+
)
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
## Search
|
|
553
|
+
|
|
554
|
+
### Basic Vector Search
|
|
555
|
+
|
|
556
|
+
```python
|
|
557
|
+
search_result = client.search(
|
|
558
|
+
collection_name="my_collection",
|
|
559
|
+
query_vector=[0.18, 0.81, 0.75, 0.12],
|
|
560
|
+
limit=5
|
|
561
|
+
)
|
|
562
|
+
|
|
563
|
+
for result in search_result:
|
|
564
|
+
print(f"ID: {result.id}, Score: {result.score}")
|
|
565
|
+
print(f"Payload: {result.payload}")
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
### Search with Score Threshold
|
|
569
|
+
|
|
570
|
+
```python
|
|
571
|
+
search_result = client.search(
|
|
572
|
+
collection_name="my_collection",
|
|
573
|
+
query_vector=[0.18, 0.81, 0.75, 0.12],
|
|
574
|
+
limit=10,
|
|
575
|
+
score_threshold=0.8
|
|
576
|
+
)
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
### Search Named Vectors
|
|
580
|
+
|
|
581
|
+
```python
|
|
582
|
+
search_result = client.search(
|
|
583
|
+
collection_name="multi_vector_collection",
|
|
584
|
+
query_vector=[0.1, 0.2, 0.3, 0.4],
|
|
585
|
+
using="text",
|
|
586
|
+
limit=5
|
|
587
|
+
)
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
### Search without Vectors
|
|
591
|
+
|
|
592
|
+
```python
|
|
593
|
+
search_result = client.search(
|
|
594
|
+
collection_name="my_collection",
|
|
595
|
+
query_vector=[0.18, 0.81, 0.75, 0.12],
|
|
596
|
+
limit=5,
|
|
597
|
+
with_payload=True,
|
|
598
|
+
with_vectors=False
|
|
599
|
+
)
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
### Text Query with FastEmbed
|
|
603
|
+
|
|
604
|
+
```python
|
|
605
|
+
search_result = client.query(
|
|
606
|
+
collection_name="demo_collection",
|
|
607
|
+
query_text="This is a query document",
|
|
608
|
+
limit=5
|
|
609
|
+
)
|
|
610
|
+
|
|
611
|
+
for result in search_result:
|
|
612
|
+
print(f"Score: {result.score}, Text: {result.payload}")
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
## Filtering
|
|
616
|
+
|
|
617
|
+
### Match Filter
|
|
618
|
+
|
|
619
|
+
```python
|
|
620
|
+
from qdrant_client.models import Filter, FieldCondition, MatchValue
|
|
621
|
+
|
|
622
|
+
search_result = client.search(
|
|
623
|
+
collection_name="my_collection",
|
|
624
|
+
query_vector=[0.2, 0.1, 0.9, 0.7],
|
|
625
|
+
query_filter=Filter(
|
|
626
|
+
must=[
|
|
627
|
+
FieldCondition(
|
|
628
|
+
key="city",
|
|
629
|
+
match=MatchValue(value="London")
|
|
630
|
+
)
|
|
631
|
+
]
|
|
632
|
+
),
|
|
633
|
+
limit=5
|
|
634
|
+
)
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
### Range Filter
|
|
638
|
+
|
|
639
|
+
```python
|
|
640
|
+
from qdrant_client.models import Filter, FieldCondition, Range
|
|
641
|
+
|
|
642
|
+
search_result = client.search(
|
|
643
|
+
collection_name="my_collection",
|
|
644
|
+
query_vector=[0.2, 0.1, 0.9, 0.7],
|
|
645
|
+
query_filter=Filter(
|
|
646
|
+
must=[
|
|
647
|
+
FieldCondition(
|
|
648
|
+
key="price",
|
|
649
|
+
range=Range(gte=1.0, lt=3.0)
|
|
650
|
+
)
|
|
651
|
+
]
|
|
652
|
+
),
|
|
653
|
+
limit=5
|
|
654
|
+
)
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
### Multiple Conditions (AND)
|
|
658
|
+
|
|
659
|
+
```python
|
|
660
|
+
from qdrant_client.models import Filter, FieldCondition, MatchValue, Range
|
|
661
|
+
|
|
662
|
+
search_result = client.search(
|
|
663
|
+
collection_name="my_collection",
|
|
664
|
+
query_vector=[0.2, 0.1, 0.9, 0.7],
|
|
665
|
+
query_filter=Filter(
|
|
666
|
+
must=[
|
|
667
|
+
FieldCondition(
|
|
668
|
+
key="city",
|
|
669
|
+
match=MatchValue(value="Berlin")
|
|
670
|
+
),
|
|
671
|
+
FieldCondition(
|
|
672
|
+
key="price",
|
|
673
|
+
range=Range(gte=2.0)
|
|
674
|
+
)
|
|
675
|
+
]
|
|
676
|
+
),
|
|
677
|
+
limit=5
|
|
678
|
+
)
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
### OR Conditions
|
|
682
|
+
|
|
683
|
+
```python
|
|
684
|
+
from qdrant_client.models import Filter, FieldCondition, MatchValue
|
|
685
|
+
|
|
686
|
+
search_result = client.search(
|
|
687
|
+
collection_name="my_collection",
|
|
688
|
+
query_vector=[0.2, 0.1, 0.9, 0.7],
|
|
689
|
+
query_filter=Filter(
|
|
690
|
+
should=[
|
|
691
|
+
FieldCondition(
|
|
692
|
+
key="city",
|
|
693
|
+
match=MatchValue(value="Berlin")
|
|
694
|
+
),
|
|
695
|
+
FieldCondition(
|
|
696
|
+
key="city",
|
|
697
|
+
match=MatchValue(value="London")
|
|
698
|
+
)
|
|
699
|
+
]
|
|
700
|
+
),
|
|
701
|
+
limit=5
|
|
702
|
+
)
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
### NOT Conditions
|
|
706
|
+
|
|
707
|
+
```python
|
|
708
|
+
from qdrant_client.models import Filter, FieldCondition, MatchValue
|
|
709
|
+
|
|
710
|
+
search_result = client.search(
|
|
711
|
+
collection_name="my_collection",
|
|
712
|
+
query_vector=[0.2, 0.1, 0.9, 0.7],
|
|
713
|
+
query_filter=Filter(
|
|
714
|
+
must_not=[
|
|
715
|
+
FieldCondition(
|
|
716
|
+
key="city",
|
|
717
|
+
match=MatchValue(value="Berlin")
|
|
718
|
+
)
|
|
719
|
+
]
|
|
720
|
+
),
|
|
721
|
+
limit=5
|
|
722
|
+
)
|
|
723
|
+
```
|
|
724
|
+
|
|
725
|
+
### Complex Filter
|
|
726
|
+
|
|
727
|
+
```python
|
|
728
|
+
from qdrant_client.models import Filter, FieldCondition, MatchValue, Range
|
|
729
|
+
|
|
730
|
+
search_result = client.search(
|
|
731
|
+
collection_name="my_collection",
|
|
732
|
+
query_vector=[0.2, 0.1, 0.9, 0.7],
|
|
733
|
+
query_filter=Filter(
|
|
734
|
+
must=[
|
|
735
|
+
FieldCondition(
|
|
736
|
+
key="category",
|
|
737
|
+
match=MatchValue(value="electronics")
|
|
738
|
+
)
|
|
739
|
+
],
|
|
740
|
+
should=[
|
|
741
|
+
FieldCondition(
|
|
742
|
+
key="price",
|
|
743
|
+
range=Range(lt=100)
|
|
744
|
+
),
|
|
745
|
+
FieldCondition(
|
|
746
|
+
key="discount",
|
|
747
|
+
match=MatchValue(value=True)
|
|
748
|
+
)
|
|
749
|
+
],
|
|
750
|
+
must_not=[
|
|
751
|
+
FieldCondition(
|
|
752
|
+
key="out_of_stock",
|
|
753
|
+
match=MatchValue(value=True)
|
|
754
|
+
)
|
|
755
|
+
]
|
|
756
|
+
),
|
|
757
|
+
limit=10
|
|
758
|
+
)
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
### Match Any (Array)
|
|
762
|
+
|
|
763
|
+
```python
|
|
764
|
+
from qdrant_client.models import Filter, FieldCondition, MatchAny
|
|
765
|
+
|
|
766
|
+
search_result = client.search(
|
|
767
|
+
collection_name="my_collection",
|
|
768
|
+
query_vector=[0.2, 0.1, 0.9, 0.7],
|
|
769
|
+
query_filter=Filter(
|
|
770
|
+
must=[
|
|
771
|
+
FieldCondition(
|
|
772
|
+
key="tags",
|
|
773
|
+
match=MatchAny(any=["electronics", "gadgets", "tech"])
|
|
774
|
+
)
|
|
775
|
+
]
|
|
776
|
+
),
|
|
777
|
+
limit=5
|
|
778
|
+
)
|
|
779
|
+
```
|
|
780
|
+
|
|
781
|
+
### Geo Radius Filter
|
|
782
|
+
|
|
783
|
+
```python
|
|
784
|
+
from qdrant_client.models import Filter, FieldCondition, GeoRadius, GeoPoint
|
|
785
|
+
|
|
786
|
+
search_result = client.search(
|
|
787
|
+
collection_name="my_collection",
|
|
788
|
+
query_vector=[0.2, 0.1, 0.9, 0.7],
|
|
789
|
+
query_filter=Filter(
|
|
790
|
+
must=[
|
|
791
|
+
FieldCondition(
|
|
792
|
+
key="location",
|
|
793
|
+
geo_radius=GeoRadius(
|
|
794
|
+
center=GeoPoint(lon=13.404954, lat=52.520008),
|
|
795
|
+
radius=5000.0
|
|
796
|
+
)
|
|
797
|
+
)
|
|
798
|
+
]
|
|
799
|
+
),
|
|
800
|
+
limit=5
|
|
801
|
+
)
|
|
802
|
+
```
|
|
803
|
+
|
|
804
|
+
### Is Empty Filter
|
|
805
|
+
|
|
806
|
+
```python
|
|
807
|
+
from qdrant_client.models import Filter, IsEmptyCondition
|
|
808
|
+
|
|
809
|
+
search_result = client.search(
|
|
810
|
+
collection_name="my_collection",
|
|
811
|
+
query_vector=[0.2, 0.1, 0.9, 0.7],
|
|
812
|
+
query_filter=Filter(
|
|
813
|
+
must=[
|
|
814
|
+
IsEmptyCondition(is_empty={"key": "tags"})
|
|
815
|
+
]
|
|
816
|
+
),
|
|
817
|
+
limit=5
|
|
818
|
+
)
|
|
819
|
+
```
|
|
820
|
+
|
|
821
|
+
### Is Null Filter
|
|
822
|
+
|
|
823
|
+
```python
|
|
824
|
+
from qdrant_client.models import Filter, IsNullCondition
|
|
825
|
+
|
|
826
|
+
search_result = client.search(
|
|
827
|
+
collection_name="my_collection",
|
|
828
|
+
query_vector=[0.2, 0.1, 0.9, 0.7],
|
|
829
|
+
query_filter=Filter(
|
|
830
|
+
must=[
|
|
831
|
+
IsNullCondition(is_null={"key": "description"})
|
|
832
|
+
]
|
|
833
|
+
),
|
|
834
|
+
limit=5
|
|
835
|
+
)
|
|
836
|
+
```
|
|
837
|
+
|
|
838
|
+
## Recommend
|
|
839
|
+
|
|
840
|
+
### Basic Recommend
|
|
841
|
+
|
|
842
|
+
```python
|
|
843
|
+
recommend_result = client.recommend(
|
|
844
|
+
collection_name="my_collection",
|
|
845
|
+
positive=[1, 2, 3],
|
|
846
|
+
negative=[10],
|
|
847
|
+
limit=5
|
|
848
|
+
)
|
|
849
|
+
|
|
850
|
+
for result in recommend_result:
|
|
851
|
+
print(f"ID: {result.id}, Score: {result.score}")
|
|
852
|
+
```
|
|
853
|
+
|
|
854
|
+
### Recommend with Vectors
|
|
855
|
+
|
|
856
|
+
```python
|
|
857
|
+
recommend_result = client.recommend(
|
|
858
|
+
collection_name="my_collection",
|
|
859
|
+
positive=[1, 2, [0.1, 0.2, 0.3, 0.4]],
|
|
860
|
+
negative=[[0.9, 0.8, 0.7, 0.6]],
|
|
861
|
+
limit=5
|
|
862
|
+
)
|
|
863
|
+
```
|
|
864
|
+
|
|
865
|
+
### Recommend with Filter
|
|
866
|
+
|
|
867
|
+
```python
|
|
868
|
+
from qdrant_client.models import Filter, FieldCondition, MatchValue
|
|
869
|
+
|
|
870
|
+
recommend_result = client.recommend(
|
|
871
|
+
collection_name="my_collection",
|
|
872
|
+
positive=[1, 2, 3],
|
|
873
|
+
negative=[10],
|
|
874
|
+
query_filter=Filter(
|
|
875
|
+
must=[
|
|
876
|
+
FieldCondition(
|
|
877
|
+
key="category",
|
|
878
|
+
match=MatchValue(value="electronics")
|
|
879
|
+
)
|
|
880
|
+
]
|
|
881
|
+
),
|
|
882
|
+
limit=5
|
|
883
|
+
)
|
|
884
|
+
```
|
|
885
|
+
|
|
886
|
+
### Recommend Strategy
|
|
887
|
+
|
|
888
|
+
```python
|
|
889
|
+
from qdrant_client.models import RecommendStrategy
|
|
890
|
+
|
|
891
|
+
recommend_result = client.recommend(
|
|
892
|
+
collection_name="my_collection",
|
|
893
|
+
positive=[1, 2, 3],
|
|
894
|
+
negative=[10],
|
|
895
|
+
strategy=RecommendStrategy.AVERAGE_VECTOR,
|
|
896
|
+
limit=5
|
|
897
|
+
)
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
### Recommend Named Vectors
|
|
901
|
+
|
|
902
|
+
```python
|
|
903
|
+
recommend_result = client.recommend(
|
|
904
|
+
collection_name="multi_vector_collection",
|
|
905
|
+
positive=[1, 2],
|
|
906
|
+
negative=[10],
|
|
907
|
+
using="text",
|
|
908
|
+
limit=5
|
|
909
|
+
)
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
## Discover
|
|
913
|
+
|
|
914
|
+
### Basic Discover
|
|
915
|
+
|
|
916
|
+
```python
|
|
917
|
+
from qdrant_client.models import ContextPair
|
|
918
|
+
|
|
919
|
+
discover_result = client.discover(
|
|
920
|
+
collection_name="my_collection",
|
|
921
|
+
target=100,
|
|
922
|
+
context=[
|
|
923
|
+
ContextPair(positive=200, negative=300),
|
|
924
|
+
ContextPair(positive=150, negative=250)
|
|
925
|
+
],
|
|
926
|
+
limit=10
|
|
927
|
+
)
|
|
928
|
+
```
|
|
929
|
+
|
|
930
|
+
### Discover with Filter
|
|
931
|
+
|
|
932
|
+
```python
|
|
933
|
+
from qdrant_client.models import ContextPair, Filter, FieldCondition, MatchValue
|
|
934
|
+
|
|
935
|
+
discover_result = client.discover(
|
|
936
|
+
collection_name="my_collection",
|
|
937
|
+
target=100,
|
|
938
|
+
context=[
|
|
939
|
+
ContextPair(positive=200, negative=300)
|
|
940
|
+
],
|
|
941
|
+
query_filter=Filter(
|
|
942
|
+
must=[
|
|
943
|
+
FieldCondition(
|
|
944
|
+
key="active",
|
|
945
|
+
match=MatchValue(value=True)
|
|
946
|
+
)
|
|
947
|
+
]
|
|
948
|
+
),
|
|
949
|
+
limit=10
|
|
950
|
+
)
|
|
951
|
+
```
|
|
952
|
+
|
|
953
|
+
## Query API (Universal)
|
|
954
|
+
|
|
955
|
+
### Vector Query
|
|
956
|
+
|
|
957
|
+
```python
|
|
958
|
+
from qdrant_client.models import QueryRequest, VectorQuery
|
|
959
|
+
|
|
960
|
+
query_result = client.query_points(
|
|
961
|
+
collection_name="my_collection",
|
|
962
|
+
query=[0.1, 0.2, 0.3, 0.4],
|
|
963
|
+
limit=10
|
|
964
|
+
)
|
|
965
|
+
```
|
|
966
|
+
|
|
967
|
+
### Recommend Query
|
|
968
|
+
|
|
969
|
+
```python
|
|
970
|
+
from qdrant_client.models import RecommendQuery
|
|
971
|
+
|
|
972
|
+
query_result = client.query_points(
|
|
973
|
+
collection_name="my_collection",
|
|
974
|
+
query=RecommendQuery(
|
|
975
|
+
recommend=RecommendInput(
|
|
976
|
+
positive=[100, 231],
|
|
977
|
+
negative=[718]
|
|
978
|
+
)
|
|
979
|
+
),
|
|
980
|
+
limit=10
|
|
981
|
+
)
|
|
982
|
+
```
|
|
983
|
+
|
|
984
|
+
### Discover Query
|
|
985
|
+
|
|
986
|
+
```python
|
|
987
|
+
from qdrant_client.models import DiscoverQuery, ContextPair
|
|
988
|
+
|
|
989
|
+
query_result = client.query_points(
|
|
990
|
+
collection_name="my_collection",
|
|
991
|
+
query=DiscoverQuery(
|
|
992
|
+
discover=DiscoverInput(
|
|
993
|
+
target=100,
|
|
994
|
+
context=[
|
|
995
|
+
ContextPair(positive=200, negative=300)
|
|
996
|
+
]
|
|
997
|
+
)
|
|
998
|
+
),
|
|
999
|
+
limit=10
|
|
1000
|
+
)
|
|
1001
|
+
```
|
|
1002
|
+
|
|
1003
|
+
### Context Query
|
|
1004
|
+
|
|
1005
|
+
```python
|
|
1006
|
+
from qdrant_client.models import ContextQuery, ContextPair
|
|
1007
|
+
|
|
1008
|
+
query_result = client.query_points(
|
|
1009
|
+
collection_name="my_collection",
|
|
1010
|
+
query=ContextQuery(
|
|
1011
|
+
context=[
|
|
1012
|
+
ContextPair(positive=100, negative=718),
|
|
1013
|
+
ContextPair(positive=200, negative=300)
|
|
1014
|
+
]
|
|
1015
|
+
),
|
|
1016
|
+
limit=10
|
|
1017
|
+
)
|
|
1018
|
+
```
|
|
1019
|
+
|
|
1020
|
+
## Batch Operations
|
|
1021
|
+
|
|
1022
|
+
### Batch Search
|
|
1023
|
+
|
|
1024
|
+
```python
|
|
1025
|
+
from qdrant_client.models import SearchRequest, Filter, FieldCondition, MatchValue
|
|
1026
|
+
|
|
1027
|
+
requests = [
|
|
1028
|
+
SearchRequest(
|
|
1029
|
+
vector=[0.1, 0.2, 0.3, 0.4],
|
|
1030
|
+
limit=5,
|
|
1031
|
+
filter=Filter(
|
|
1032
|
+
must=[
|
|
1033
|
+
FieldCondition(
|
|
1034
|
+
key="category",
|
|
1035
|
+
match=MatchValue(value="electronics")
|
|
1036
|
+
)
|
|
1037
|
+
]
|
|
1038
|
+
)
|
|
1039
|
+
),
|
|
1040
|
+
SearchRequest(
|
|
1041
|
+
vector=[0.5, 0.6, 0.7, 0.8],
|
|
1042
|
+
limit=5,
|
|
1043
|
+
filter=Filter(
|
|
1044
|
+
must=[
|
|
1045
|
+
FieldCondition(
|
|
1046
|
+
key="category",
|
|
1047
|
+
match=MatchValue(value="books")
|
|
1048
|
+
)
|
|
1049
|
+
]
|
|
1050
|
+
)
|
|
1051
|
+
)
|
|
1052
|
+
]
|
|
1053
|
+
|
|
1054
|
+
results = client.search_batch(
|
|
1055
|
+
collection_name="my_collection",
|
|
1056
|
+
requests=requests
|
|
1057
|
+
)
|
|
1058
|
+
|
|
1059
|
+
for i, result in enumerate(results):
|
|
1060
|
+
print(f"Results for request {i}:")
|
|
1061
|
+
for point in result:
|
|
1062
|
+
print(f" ID: {point.id}, Score: {point.score}")
|
|
1063
|
+
```
|
|
1064
|
+
|
|
1065
|
+
### Batch Query
|
|
1066
|
+
|
|
1067
|
+
```python
|
|
1068
|
+
from qdrant_client.models import QueryRequest
|
|
1069
|
+
|
|
1070
|
+
requests = [
|
|
1071
|
+
QueryRequest(
|
|
1072
|
+
query=[0.1, 0.2, 0.3, 0.4],
|
|
1073
|
+
limit=5
|
|
1074
|
+
),
|
|
1075
|
+
QueryRequest(
|
|
1076
|
+
query=[0.5, 0.6, 0.7, 0.8],
|
|
1077
|
+
limit=5
|
|
1078
|
+
)
|
|
1079
|
+
]
|
|
1080
|
+
|
|
1081
|
+
results = client.query_batch_points(
|
|
1082
|
+
collection_name="my_collection",
|
|
1083
|
+
requests=requests
|
|
1084
|
+
)
|
|
1085
|
+
```
|
|
1086
|
+
|
|
1087
|
+
### Batch Recommend
|
|
1088
|
+
|
|
1089
|
+
```python
|
|
1090
|
+
from qdrant_client.models import RecommendRequest, Filter, FieldCondition, MatchValue
|
|
1091
|
+
|
|
1092
|
+
requests = [
|
|
1093
|
+
RecommendRequest(
|
|
1094
|
+
positive=[100, 231],
|
|
1095
|
+
negative=[718],
|
|
1096
|
+
limit=10
|
|
1097
|
+
),
|
|
1098
|
+
RecommendRequest(
|
|
1099
|
+
positive=[500, 600],
|
|
1100
|
+
negative=[700, 800],
|
|
1101
|
+
limit=10,
|
|
1102
|
+
filter=Filter(
|
|
1103
|
+
must=[
|
|
1104
|
+
FieldCondition(
|
|
1105
|
+
key="active",
|
|
1106
|
+
match=MatchValue(value=True)
|
|
1107
|
+
)
|
|
1108
|
+
]
|
|
1109
|
+
)
|
|
1110
|
+
)
|
|
1111
|
+
]
|
|
1112
|
+
|
|
1113
|
+
results = client.recommend_batch(
|
|
1114
|
+
collection_name="my_collection",
|
|
1115
|
+
requests=requests
|
|
1116
|
+
)
|
|
1117
|
+
```
|
|
1118
|
+
|
|
1119
|
+
### Batch Update Points
|
|
1120
|
+
|
|
1121
|
+
```python
|
|
1122
|
+
from qdrant_client.models import (
|
|
1123
|
+
PointStruct,
|
|
1124
|
+
UpsertOperation,
|
|
1125
|
+
DeleteOperation,
|
|
1126
|
+
SetPayloadOperation,
|
|
1127
|
+
PointIdsList,
|
|
1128
|
+
UpdateStatus
|
|
1129
|
+
)
|
|
1130
|
+
|
|
1131
|
+
client.batch_update_points(
|
|
1132
|
+
collection_name="my_collection",
|
|
1133
|
+
update_operations=[
|
|
1134
|
+
UpsertOperation(
|
|
1135
|
+
upsert=PointsList(
|
|
1136
|
+
points=[
|
|
1137
|
+
PointStruct(
|
|
1138
|
+
id=1,
|
|
1139
|
+
vector=[1.0, 2.0, 3.0, 4.0],
|
|
1140
|
+
payload={"title": "Item 1"}
|
|
1141
|
+
)
|
|
1142
|
+
]
|
|
1143
|
+
)
|
|
1144
|
+
),
|
|
1145
|
+
DeleteOperation(
|
|
1146
|
+
delete=PointIdsList(points=[5, 6, 7])
|
|
1147
|
+
),
|
|
1148
|
+
SetPayloadOperation(
|
|
1149
|
+
set_payload=SetPayload(
|
|
1150
|
+
payload={"updated": True},
|
|
1151
|
+
points=[1, 2, 3]
|
|
1152
|
+
)
|
|
1153
|
+
)
|
|
1154
|
+
]
|
|
1155
|
+
)
|
|
1156
|
+
```
|
|
1157
|
+
|
|
1158
|
+
### Mixed Batch Operations
|
|
1159
|
+
|
|
1160
|
+
```python
|
|
1161
|
+
from qdrant_client.models import (
|
|
1162
|
+
UpsertOperation,
|
|
1163
|
+
UpdateVectorsOperation,
|
|
1164
|
+
DeletePayloadOperation,
|
|
1165
|
+
PointStruct,
|
|
1166
|
+
PointsList,
|
|
1167
|
+
UpdateVectors,
|
|
1168
|
+
PointVectors,
|
|
1169
|
+
DeletePayload,
|
|
1170
|
+
PointIdsList
|
|
1171
|
+
)
|
|
1172
|
+
|
|
1173
|
+
client.batch_update_points(
|
|
1174
|
+
collection_name="my_collection",
|
|
1175
|
+
update_operations=[
|
|
1176
|
+
UpsertOperation(
|
|
1177
|
+
upsert=PointsList(
|
|
1178
|
+
points=[
|
|
1179
|
+
PointStruct(
|
|
1180
|
+
id=1,
|
|
1181
|
+
vector=[1.0, 2.0, 3.0, 4.0],
|
|
1182
|
+
payload={}
|
|
1183
|
+
)
|
|
1184
|
+
]
|
|
1185
|
+
)
|
|
1186
|
+
),
|
|
1187
|
+
UpdateVectorsOperation(
|
|
1188
|
+
update_vectors=UpdateVectors(
|
|
1189
|
+
points=[
|
|
1190
|
+
PointVectors(
|
|
1191
|
+
id=2,
|
|
1192
|
+
vector=[5.0, 6.0, 7.0, 8.0]
|
|
1193
|
+
)
|
|
1194
|
+
]
|
|
1195
|
+
)
|
|
1196
|
+
),
|
|
1197
|
+
DeletePayloadOperation(
|
|
1198
|
+
delete_payload=DeletePayload(
|
|
1199
|
+
keys=["old_field"],
|
|
1200
|
+
points=PointIdsList(points=[3, 4])
|
|
1201
|
+
)
|
|
1202
|
+
)
|
|
1203
|
+
]
|
|
1204
|
+
)
|
|
1205
|
+
```
|
|
1206
|
+
|
|
1207
|
+
## Payload Operations
|
|
1208
|
+
|
|
1209
|
+
### Set Payload
|
|
1210
|
+
|
|
1211
|
+
```python
|
|
1212
|
+
from datetime import datetime
|
|
1213
|
+
|
|
1214
|
+
client.set_payload(
|
|
1215
|
+
collection_name="my_collection",
|
|
1216
|
+
payload={
|
|
1217
|
+
"updated_at": datetime.now().isoformat(),
|
|
1218
|
+
"verified": True
|
|
1219
|
+
},
|
|
1220
|
+
points=[1, 2, 3]
|
|
1221
|
+
)
|
|
1222
|
+
```
|
|
1223
|
+
|
|
1224
|
+
### Set Payload with Filter
|
|
1225
|
+
|
|
1226
|
+
```python
|
|
1227
|
+
from qdrant_client.models import Filter, FieldCondition, Range
|
|
1228
|
+
|
|
1229
|
+
client.set_payload(
|
|
1230
|
+
collection_name="my_collection",
|
|
1231
|
+
payload={"promoted": True},
|
|
1232
|
+
points=Filter(
|
|
1233
|
+
must=[
|
|
1234
|
+
FieldCondition(
|
|
1235
|
+
key="price",
|
|
1236
|
+
range=Range(lt=50)
|
|
1237
|
+
)
|
|
1238
|
+
]
|
|
1239
|
+
)
|
|
1240
|
+
)
|
|
1241
|
+
```
|
|
1242
|
+
|
|
1243
|
+
### Overwrite Payload
|
|
1244
|
+
|
|
1245
|
+
```python
|
|
1246
|
+
client.overwrite_payload(
|
|
1247
|
+
collection_name="my_collection",
|
|
1248
|
+
payload={
|
|
1249
|
+
"title": "New Title",
|
|
1250
|
+
"price": 99.99
|
|
1251
|
+
},
|
|
1252
|
+
points=[1, 2]
|
|
1253
|
+
)
|
|
1254
|
+
```
|
|
1255
|
+
|
|
1256
|
+
### Delete Payload Keys
|
|
1257
|
+
|
|
1258
|
+
```python
|
|
1259
|
+
client.delete_payload(
|
|
1260
|
+
collection_name="my_collection",
|
|
1261
|
+
keys=["old_field", "deprecated_field"],
|
|
1262
|
+
points=[1, 2, 3]
|
|
1263
|
+
)
|
|
1264
|
+
```
|
|
1265
|
+
|
|
1266
|
+
### Clear Payload
|
|
1267
|
+
|
|
1268
|
+
```python
|
|
1269
|
+
client.clear_payload(
|
|
1270
|
+
collection_name="my_collection",
|
|
1271
|
+
points_selector=[1, 2, 3]
|
|
1272
|
+
)
|
|
1273
|
+
```
|
|
1274
|
+
|
|
1275
|
+
## Payload Indexing
|
|
1276
|
+
|
|
1277
|
+
### Create Payload Index - Keyword
|
|
1278
|
+
|
|
1279
|
+
```python
|
|
1280
|
+
client.create_payload_index(
|
|
1281
|
+
collection_name="my_collection",
|
|
1282
|
+
field_name="city",
|
|
1283
|
+
field_schema="keyword"
|
|
1284
|
+
)
|
|
1285
|
+
```
|
|
1286
|
+
|
|
1287
|
+
### Create Payload Index - Integer
|
|
1288
|
+
|
|
1289
|
+
```python
|
|
1290
|
+
client.create_payload_index(
|
|
1291
|
+
collection_name="my_collection",
|
|
1292
|
+
field_name="price",
|
|
1293
|
+
field_schema="integer"
|
|
1294
|
+
)
|
|
1295
|
+
```
|
|
1296
|
+
|
|
1297
|
+
### Create Payload Index - Float
|
|
1298
|
+
|
|
1299
|
+
```python
|
|
1300
|
+
client.create_payload_index(
|
|
1301
|
+
collection_name="my_collection",
|
|
1302
|
+
field_name="rating",
|
|
1303
|
+
field_schema="float"
|
|
1304
|
+
)
|
|
1305
|
+
```
|
|
1306
|
+
|
|
1307
|
+
### Create Payload Index - Geo
|
|
1308
|
+
|
|
1309
|
+
```python
|
|
1310
|
+
client.create_payload_index(
|
|
1311
|
+
collection_name="my_collection",
|
|
1312
|
+
field_name="location",
|
|
1313
|
+
field_schema="geo"
|
|
1314
|
+
)
|
|
1315
|
+
```
|
|
1316
|
+
|
|
1317
|
+
### Create Payload Index - Text
|
|
1318
|
+
|
|
1319
|
+
```python
|
|
1320
|
+
from qdrant_client.models import TextIndexParams, TokenizerType
|
|
1321
|
+
|
|
1322
|
+
client.create_payload_index(
|
|
1323
|
+
collection_name="my_collection",
|
|
1324
|
+
field_name="description",
|
|
1325
|
+
field_schema=TextIndexParams(
|
|
1326
|
+
type="text",
|
|
1327
|
+
tokenizer=TokenizerType.WORD,
|
|
1328
|
+
min_token_len=2,
|
|
1329
|
+
max_token_len=20,
|
|
1330
|
+
lowercase=True
|
|
1331
|
+
)
|
|
1332
|
+
)
|
|
1333
|
+
```
|
|
1334
|
+
|
|
1335
|
+
### Delete Payload Index
|
|
1336
|
+
|
|
1337
|
+
```python
|
|
1338
|
+
client.delete_payload_index(
|
|
1339
|
+
collection_name="my_collection",
|
|
1340
|
+
field_name="old_index_field"
|
|
1341
|
+
)
|
|
1342
|
+
```
|
|
1343
|
+
|
|
1344
|
+
## Snapshots
|
|
1345
|
+
|
|
1346
|
+
### Create Collection Snapshot
|
|
1347
|
+
|
|
1348
|
+
```python
|
|
1349
|
+
snapshot_info = client.create_snapshot(
|
|
1350
|
+
collection_name="my_collection"
|
|
1351
|
+
)
|
|
1352
|
+
print(f"Snapshot created: {snapshot_info.name}")
|
|
1353
|
+
```
|
|
1354
|
+
|
|
1355
|
+
### List Collection Snapshots
|
|
1356
|
+
|
|
1357
|
+
```python
|
|
1358
|
+
snapshots = client.list_snapshots(
|
|
1359
|
+
collection_name="my_collection"
|
|
1360
|
+
)
|
|
1361
|
+
|
|
1362
|
+
for snapshot in snapshots:
|
|
1363
|
+
print(f"Snapshot: {snapshot.name}, Size: {snapshot.size}")
|
|
1364
|
+
```
|
|
1365
|
+
|
|
1366
|
+
### Delete Collection Snapshot
|
|
1367
|
+
|
|
1368
|
+
```python
|
|
1369
|
+
client.delete_snapshot(
|
|
1370
|
+
collection_name="my_collection",
|
|
1371
|
+
snapshot_name="snapshot_2025-01-15-10-30-00"
|
|
1372
|
+
)
|
|
1373
|
+
```
|
|
1374
|
+
|
|
1375
|
+
### Create Full Storage Snapshot
|
|
1376
|
+
|
|
1377
|
+
```python
|
|
1378
|
+
snapshot_info = client.create_full_snapshot()
|
|
1379
|
+
print(f"Full snapshot created: {snapshot_info.name}")
|
|
1380
|
+
```
|
|
1381
|
+
|
|
1382
|
+
### List Full Snapshots
|
|
1383
|
+
|
|
1384
|
+
```python
|
|
1385
|
+
snapshots = client.list_full_snapshots()
|
|
1386
|
+
for snapshot in snapshots:
|
|
1387
|
+
print(f"Full snapshot: {snapshot.name}")
|
|
1388
|
+
```
|
|
1389
|
+
|
|
1390
|
+
### Download Snapshot
|
|
1391
|
+
|
|
1392
|
+
```python
|
|
1393
|
+
client.download_snapshot(
|
|
1394
|
+
collection_name="my_collection",
|
|
1395
|
+
snapshot_name="snapshot_2025-01-15-10-30-00",
|
|
1396
|
+
snapshot_path="./backups/snapshot.snapshot"
|
|
1397
|
+
)
|
|
1398
|
+
```
|
|
1399
|
+
|
|
1400
|
+
## Cluster Operations
|
|
1401
|
+
|
|
1402
|
+
### Get Cluster Info
|
|
1403
|
+
|
|
1404
|
+
```python
|
|
1405
|
+
cluster_info = client.cluster_status()
|
|
1406
|
+
print(f"Peers: {cluster_info.peers}")
|
|
1407
|
+
print(f"Raft info: {cluster_info.raft_info}")
|
|
1408
|
+
```
|
|
1409
|
+
|
|
1410
|
+
## Async Operations
|
|
1411
|
+
|
|
1412
|
+
### Async Client Usage
|
|
1413
|
+
|
|
1414
|
+
```python
|
|
1415
|
+
from qdrant_client import AsyncQdrantClient
|
|
1416
|
+
from qdrant_client.models import Distance, VectorParams, PointStruct
|
|
1417
|
+
import asyncio
|
|
1418
|
+
|
|
1419
|
+
async def main():
|
|
1420
|
+
client = AsyncQdrantClient(url="http://localhost:6333")
|
|
1421
|
+
|
|
1422
|
+
# Create collection
|
|
1423
|
+
await client.create_collection(
|
|
1424
|
+
collection_name="async_collection",
|
|
1425
|
+
vectors_config=VectorParams(size=4, distance=Distance.COSINE)
|
|
1426
|
+
)
|
|
1427
|
+
|
|
1428
|
+
# Upsert points
|
|
1429
|
+
await client.upsert(
|
|
1430
|
+
collection_name="async_collection",
|
|
1431
|
+
points=[
|
|
1432
|
+
PointStruct(
|
|
1433
|
+
id=1,
|
|
1434
|
+
vector=[0.1, 0.2, 0.3, 0.4],
|
|
1435
|
+
payload={"title": "Async document"}
|
|
1436
|
+
)
|
|
1437
|
+
]
|
|
1438
|
+
)
|
|
1439
|
+
|
|
1440
|
+
# Search
|
|
1441
|
+
results = await client.search(
|
|
1442
|
+
collection_name="async_collection",
|
|
1443
|
+
query_vector=[0.1, 0.2, 0.3, 0.4],
|
|
1444
|
+
limit=5
|
|
1445
|
+
)
|
|
1446
|
+
|
|
1447
|
+
for result in results:
|
|
1448
|
+
print(f"ID: {result.id}, Score: {result.score}")
|
|
1449
|
+
|
|
1450
|
+
await client.close()
|
|
1451
|
+
|
|
1452
|
+
asyncio.run(main())
|
|
1453
|
+
```
|
|
1454
|
+
|
|
1455
|
+
### Async Context Manager
|
|
1456
|
+
|
|
1457
|
+
```python
|
|
1458
|
+
from qdrant_client import AsyncQdrantClient
|
|
1459
|
+
|
|
1460
|
+
async def main():
|
|
1461
|
+
async with AsyncQdrantClient(url="http://localhost:6333") as client:
|
|
1462
|
+
collections = await client.get_collections()
|
|
1463
|
+
print(collections)
|
|
1464
|
+
|
|
1465
|
+
asyncio.run(main())
|
|
1466
|
+
```
|
|
1467
|
+
|
|
1468
|
+
## Error Handling
|
|
1469
|
+
|
|
1470
|
+
### Basic Error Handling
|
|
1471
|
+
|
|
1472
|
+
```python
|
|
1473
|
+
try:
|
|
1474
|
+
search_result = client.search(
|
|
1475
|
+
collection_name="my_collection",
|
|
1476
|
+
query_vector=[0.1, 0.2, 0.3, 0.4],
|
|
1477
|
+
limit=10
|
|
1478
|
+
)
|
|
1479
|
+
except Exception as e:
|
|
1480
|
+
print(f"Search failed: {e}")
|
|
1481
|
+
```
|
|
1482
|
+
|
|
1483
|
+
### Check Collection Exists Before Operations
|
|
1484
|
+
|
|
1485
|
+
```python
|
|
1486
|
+
if not client.collection_exists("my_collection"):
|
|
1487
|
+
from qdrant_client.models import Distance, VectorParams
|
|
1488
|
+
|
|
1489
|
+
client.create_collection(
|
|
1490
|
+
collection_name="my_collection",
|
|
1491
|
+
vectors_config=VectorParams(size=384, distance=Distance.COSINE)
|
|
1492
|
+
)
|
|
1493
|
+
```
|
|
1494
|
+
|
|
1495
|
+
### Retry Logic
|
|
1496
|
+
|
|
1497
|
+
```python
|
|
1498
|
+
import time
|
|
1499
|
+
from qdrant_client.http.exceptions import UnexpectedResponse
|
|
1500
|
+
|
|
1501
|
+
def search_with_retry(client, collection_name, query_vector, max_retries=3):
|
|
1502
|
+
for attempt in range(max_retries):
|
|
1503
|
+
try:
|
|
1504
|
+
return client.search(
|
|
1505
|
+
collection_name=collection_name,
|
|
1506
|
+
query_vector=query_vector,
|
|
1507
|
+
limit=5
|
|
1508
|
+
)
|
|
1509
|
+
except UnexpectedResponse as e:
|
|
1510
|
+
if attempt == max_retries - 1:
|
|
1511
|
+
raise
|
|
1512
|
+
time.sleep(2 ** attempt)
|
|
1513
|
+
|
|
1514
|
+
results = search_with_retry(client, "my_collection", [0.1, 0.2, 0.3, 0.4])
|
|
1515
|
+
```
|
|
1516
|
+
|
|
1517
|
+
## Complete Example
|
|
1518
|
+
|
|
1519
|
+
```python
|
|
1520
|
+
from qdrant_client import QdrantClient
|
|
1521
|
+
from qdrant_client.models import Distance, VectorParams, PointStruct, Filter, FieldCondition, MatchValue, Range
|
|
1522
|
+
import numpy as np
|
|
1523
|
+
|
|
1524
|
+
# Initialize client
|
|
1525
|
+
client = QdrantClient(url="http://localhost:6333")
|
|
1526
|
+
|
|
1527
|
+
collection_name = "products"
|
|
1528
|
+
|
|
1529
|
+
# Create collection
|
|
1530
|
+
if not client.collection_exists(collection_name):
|
|
1531
|
+
client.create_collection(
|
|
1532
|
+
collection_name=collection_name,
|
|
1533
|
+
vectors_config=VectorParams(size=4, distance=Distance.COSINE)
|
|
1534
|
+
)
|
|
1535
|
+
|
|
1536
|
+
# Upsert points
|
|
1537
|
+
client.upsert(
|
|
1538
|
+
collection_name=collection_name,
|
|
1539
|
+
points=[
|
|
1540
|
+
PointStruct(
|
|
1541
|
+
id=1,
|
|
1542
|
+
vector=[0.05, 0.61, 0.76, 0.74],
|
|
1543
|
+
payload={
|
|
1544
|
+
"name": "Product A",
|
|
1545
|
+
"category": "electronics",
|
|
1546
|
+
"price": 299.99,
|
|
1547
|
+
"in_stock": True
|
|
1548
|
+
}
|
|
1549
|
+
),
|
|
1550
|
+
PointStruct(
|
|
1551
|
+
id=2,
|
|
1552
|
+
vector=[0.19, 0.81, 0.75, 0.11],
|
|
1553
|
+
payload={
|
|
1554
|
+
"name": "Product B",
|
|
1555
|
+
"category": "electronics",
|
|
1556
|
+
"price": 199.99,
|
|
1557
|
+
"in_stock": True
|
|
1558
|
+
}
|
|
1559
|
+
),
|
|
1560
|
+
PointStruct(
|
|
1561
|
+
id=3,
|
|
1562
|
+
vector=[0.36, 0.55, 0.47, 0.94],
|
|
1563
|
+
payload={
|
|
1564
|
+
"name": "Product C",
|
|
1565
|
+
"category": "books",
|
|
1566
|
+
"price": 29.99,
|
|
1567
|
+
"in_stock": False
|
|
1568
|
+
}
|
|
1569
|
+
),
|
|
1570
|
+
PointStruct(
|
|
1571
|
+
id=4,
|
|
1572
|
+
vector=[0.88, 0.22, 0.33, 0.44],
|
|
1573
|
+
payload={
|
|
1574
|
+
"name": "Product D",
|
|
1575
|
+
"category": "electronics",
|
|
1576
|
+
"price": 399.99,
|
|
1577
|
+
"in_stock": True
|
|
1578
|
+
}
|
|
1579
|
+
)
|
|
1580
|
+
],
|
|
1581
|
+
wait=True
|
|
1582
|
+
)
|
|
1583
|
+
|
|
1584
|
+
# Basic search
|
|
1585
|
+
print("=== Basic Search ===")
|
|
1586
|
+
results = client.search(
|
|
1587
|
+
collection_name=collection_name,
|
|
1588
|
+
query_vector=[0.2, 0.7, 0.8, 0.1],
|
|
1589
|
+
limit=3
|
|
1590
|
+
)
|
|
1591
|
+
|
|
1592
|
+
for result in results:
|
|
1593
|
+
print(f"{result.payload['name']} - Score: {result.score:.4f}")
|
|
1594
|
+
|
|
1595
|
+
# Filtered search
|
|
1596
|
+
print("\n=== Filtered Search (electronics under $300) ===")
|
|
1597
|
+
filtered_results = client.search(
|
|
1598
|
+
collection_name=collection_name,
|
|
1599
|
+
query_vector=[0.2, 0.7, 0.8, 0.1],
|
|
1600
|
+
query_filter=Filter(
|
|
1601
|
+
must=[
|
|
1602
|
+
FieldCondition(
|
|
1603
|
+
key="category",
|
|
1604
|
+
match=MatchValue(value="electronics")
|
|
1605
|
+
),
|
|
1606
|
+
FieldCondition(
|
|
1607
|
+
key="price",
|
|
1608
|
+
range=Range(lt=300)
|
|
1609
|
+
),
|
|
1610
|
+
FieldCondition(
|
|
1611
|
+
key="in_stock",
|
|
1612
|
+
match=MatchValue(value=True)
|
|
1613
|
+
)
|
|
1614
|
+
]
|
|
1615
|
+
),
|
|
1616
|
+
limit=5
|
|
1617
|
+
)
|
|
1618
|
+
|
|
1619
|
+
for result in filtered_results:
|
|
1620
|
+
print(f"{result.payload['name']} - ${result.payload['price']}")
|
|
1621
|
+
|
|
1622
|
+
# Count points
|
|
1623
|
+
count = client.count(collection_name=collection_name, exact=True)
|
|
1624
|
+
print(f"\n=== Total Points: {count.count} ===")
|
|
1625
|
+
|
|
1626
|
+
# Recommend
|
|
1627
|
+
print("\n=== Recommendations based on Product A ===")
|
|
1628
|
+
recommendations = client.recommend(
|
|
1629
|
+
collection_name=collection_name,
|
|
1630
|
+
positive=[1],
|
|
1631
|
+
negative=[],
|
|
1632
|
+
limit=3
|
|
1633
|
+
)
|
|
1634
|
+
|
|
1635
|
+
for rec in recommendations:
|
|
1636
|
+
print(f"{rec.payload['name']} - Score: {rec.score:.4f}")
|
|
1637
|
+
|
|
1638
|
+
# Scroll through all points
|
|
1639
|
+
print("\n=== All Products (via scroll) ===")
|
|
1640
|
+
records, next_offset = client.scroll(
|
|
1641
|
+
collection_name=collection_name,
|
|
1642
|
+
limit=10,
|
|
1643
|
+
with_payload=True,
|
|
1644
|
+
with_vectors=False
|
|
1645
|
+
)
|
|
1646
|
+
|
|
1647
|
+
for record in records:
|
|
1648
|
+
print(f"ID {record.id}: {record.payload['name']} - {record.payload['category']}")
|
|
1649
|
+
|
|
1650
|
+
# Cleanup
|
|
1651
|
+
client.delete_collection(collection_name)
|
|
1652
|
+
print(f"\n=== Collection '{collection_name}' deleted ===")
|
|
1653
|
+
```
|