ydb-qdrant 2.1.4 → 2.2.1

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.
Files changed (2) hide show
  1. package/README.md +127 -3
  2. package/package.json +6 -3
package/README.md CHANGED
@@ -1,7 +1,11 @@
1
1
  <img src="https://ydb-qdrant.tech/logo.svg" alt="YDB Qdrant logo" height="56">
2
2
 
3
- [![CI](https://github.com/astandrik/ydb-qdrant/actions/workflows/ci-ydb-qdrant.yml/badge.svg)](https://github.com/astandrik/ydb-qdrant/actions/workflows/ci-ydb-qdrant.yml)
3
+ [![Build](https://img.shields.io/github/actions/workflow/status/astandrik/ydb-qdrant/ci-build.yml?branch=main&label=build)](https://github.com/astandrik/ydb-qdrant/actions/workflows/ci-build.yml)
4
+ [![Tests](https://img.shields.io/github/actions/workflow/status/astandrik/ydb-qdrant/ci-tests.yml?branch=main&label=tests)](https://github.com/astandrik/ydb-qdrant/actions/workflows/ci-tests.yml)
5
+ [![Integration Tests](https://img.shields.io/github/actions/workflow/status/astandrik/ydb-qdrant/ci-integration.yml?branch=main&label=integration%20tests)](https://github.com/astandrik/ydb-qdrant/actions/workflows/ci-integration.yml)
6
+ [![Coverage](https://coveralls.io/repos/github/astandrik/ydb-qdrant/badge.svg?branch=main)](https://coveralls.io/github/astandrik/ydb-qdrant?branch=main)
4
7
  [![npm version](https://img.shields.io/npm/v/ydb-qdrant.svg)](https://www.npmjs.com/package/ydb-qdrant)
8
+ [![Docker Image](https://img.shields.io/badge/docker-ghcr.io%2Fastandrik%2Fydb--qdrant-blue?logo=docker)](https://github.com/users/astandrik/packages/container/package/ydb-qdrant)
5
9
  [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC)
6
10
 
7
11
  # YDB Qdrant-compatible Service
@@ -83,7 +87,11 @@ The package entrypoint exports a programmatic API that mirrors the Qdrant HTTP s
83
87
 
84
88
  async function main() {
85
89
  // defaultTenant is optional; defaults to "default"
86
- const client = await createYdbQdrantClient({ defaultTenant: "myapp" });
90
+ const client = await createYdbQdrantClient({
91
+ defaultTenant: "myapp",
92
+ endpoint: "grpcs://lb.etn01g9tcilcon2mrt3h.ydb.mdb.yandexcloud.net:2135",
93
+ database: "/ru-central1/b1ge4v9r1l3h1q4njclp/etn01g9tcilcon2mrt3h",
94
+ });
87
95
 
88
96
  await client.createCollection("documents", {
89
97
  vectors: {
@@ -111,7 +119,10 @@ The package entrypoint exports a programmatic API that mirrors the Qdrant HTTP s
111
119
 
112
120
  - Multi-tenant usage with `forTenant`:
113
121
  ```ts
114
- const client = await createYdbQdrantClient();
122
+ const client = await createYdbQdrantClient({
123
+ endpoint: "grpcs://lb.etn01g9tcilcon2mrt3h.ydb.mdb.yandexcloud.net:2135",
124
+ database: "/ru-central1/b1ge4v9r1l3h1q4njclp/etn01g9tcilcon2mrt3h",
125
+ });
115
126
  const tenantClient = client.forTenant("tenant-a");
116
127
 
117
128
  await tenantClient.upsertPoints("sessions", {
@@ -121,6 +132,41 @@ The package entrypoint exports a programmatic API that mirrors the Qdrant HTTP s
121
132
 
122
133
  The request/response shapes follow the same schemas as the HTTP API (`CreateCollectionReq`, `UpsertPointsReq`, `SearchReq`, `DeletePointsReq`), so code written against the REST API can usually be translated directly to the library calls.
123
134
 
135
+ ### Example: in-process points search with a shared client
136
+
137
+ In a typical server application you create a single `ydb-qdrant` client once and reuse it across requests. Then you can perform vector search (points search) directly in your business logic:
138
+
139
+ ```ts
140
+ import {createYdbQdrantClient} from 'ydb-qdrant';
141
+
142
+ let clientPromise: ReturnType<typeof createYdbQdrantClient> | null = null;
143
+
144
+ async function getClient() {
145
+ if (!clientPromise) {
146
+ clientPromise = createYdbQdrantClient({
147
+ defaultTenant: 'myapp',
148
+ endpoint: 'grpcs://lb.etn01g9tcilcon2mrt3h.ydb.mdb.yandexcloud.net:2135',
149
+ database: '/ru-central1/b1ge4v9r1l3h1q4njclp/etn01g9tcilcon2mrt3h',
150
+ });
151
+ }
152
+ return clientPromise;
153
+ }
154
+
155
+ export async function searchDocuments(collection: string, queryEmbedding: number[], top: number) {
156
+ const client = await getClient();
157
+
158
+ const result = await client.searchPoints(collection, {
159
+ vector: queryEmbedding,
160
+ top,
161
+ with_payload: true,
162
+ });
163
+
164
+ return result.points ?? [];
165
+ }
166
+ ```
167
+
168
+ This pattern avoids running a separate HTTP service: vector search is executed directly against YDB via the shared `createYdbQdrantClient` instance, while the rest of your code works with plain TypeScript functions.
169
+
124
170
  ## Quick Start
125
171
 
126
172
  ### Use with IDE agents (Roo Code, Cline)
@@ -182,6 +228,84 @@ Health check:
182
228
  curl -s http://localhost:8080/health
183
229
  ```
184
230
 
231
+ ### Docker (self-hosted HTTP server)
232
+
233
+ Published container: [`ghcr.io/astandrik/ydb-qdrant`](https://github.com/users/astandrik/packages/container/package/ydb-qdrant)
234
+
235
+ **Option A – pull the published image (recommended)**
236
+
237
+ ```bash
238
+ docker pull ghcr.io/astandrik/ydb-qdrant:latest
239
+
240
+ docker run -d --name ydb-qdrant \
241
+ -p 8080:8080 \
242
+ -e YDB_ENDPOINT=grpcs://ydb.serverless.yandexcloud.net:2135 \
243
+ -e YDB_DATABASE=/ru-central1/<cloud>/<db> \
244
+ -e YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS=/sa-key.json \
245
+ -v /abs/path/sa-key.json:/sa-key.json:ro \
246
+ ghcr.io/astandrik/ydb-qdrant:latest
247
+ ```
248
+
249
+ **Option B – build the image locally**
250
+
251
+ From the `ydb-qdrant/` directory:
252
+
253
+ ```bash
254
+ docker build -t ydb-qdrant:latest .
255
+
256
+ docker run -d --name ydb-qdrant \
257
+ -p 8080:8080 \
258
+ -e YDB_ENDPOINT=grpcs://ydb.serverless.yandexcloud.net:2135 \
259
+ -e YDB_DATABASE=/ru-central1/<cloud>/<db> \
260
+ -e YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS=/sa-key.json \
261
+ -v /abs/path/sa-key.json:/sa-key.json:ro \
262
+ ydb-qdrant:latest
263
+ ```
264
+
265
+ #### Docker Compose
266
+
267
+ Example `docker-compose.yml` (can be used instead of raw `docker run`):
268
+
269
+ ```yaml
270
+ services:
271
+ ydb-qdrant:
272
+ image: ghcr.io/astandrik/ydb-qdrant:latest
273
+ ports:
274
+ - "8080:8080"
275
+ env_file:
276
+ - .env
277
+ environment:
278
+ YDB_ENDPOINT: ${YDB_ENDPOINT}
279
+ YDB_DATABASE: ${YDB_DATABASE}
280
+ YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS: /sa-key.json
281
+ PORT: ${PORT:-8080}
282
+ LOG_LEVEL: ${LOG_LEVEL:-info}
283
+ volumes:
284
+ - ${YDB_SA_KEY_PATH}:/sa-key.json:ro
285
+ ```
286
+
287
+ Example `.env` (per environment):
288
+
289
+ ```bash
290
+ YDB_ENDPOINT=grpcs://ydb.serverless.yandexcloud.net:2135
291
+ YDB_DATABASE=/ru-central1/<cloud>/<db>
292
+ YDB_SA_KEY_PATH=/abs/path/to/ydb-sa.json
293
+ PORT=8080
294
+ LOG_LEVEL=info
295
+ ```
296
+
297
+ - **Updating to a newer image with Compose** (no rebuild):
298
+ - Pull the latest tag and restart the service:
299
+ ```bash
300
+ docker-compose pull ydb-qdrant
301
+ docker-compose up -d ydb-qdrant
302
+ ```
303
+
304
+ - **Environment**: uses the same variables as documented in **Configure credentials** (`YDB_ENDPOINT`, `YDB_DATABASE`, one of the `YDB_*_CREDENTIALS` options, optional `PORT`/`LOG_LEVEL`).
305
+ - **Qdrant URL for tools/clients**: set to `http://localhost:8080` (or `http://<host>:<hostPort>` if you map a different port).
306
+ - **Health check inside container**: `GET http://localhost:8080/health`.
307
+
308
+
185
309
  ## API Reference
186
310
 
187
311
  Create collection (PUT /collections/{collection}):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-qdrant",
3
- "version": "2.1.4",
3
+ "version": "2.2.1",
4
4
  "main": "dist/package/Api.js",
5
5
  "types": "dist/package/Api.d.ts",
6
6
  "exports": {
@@ -14,7 +14,9 @@
14
14
  "logo.svg"
15
15
  ],
16
16
  "scripts": {
17
- "test": "vitest run",
17
+ "test": "vitest run --exclude \"test/integration/**\"",
18
+ "test:coverage": "vitest run --coverage --exclude \"test/integration/**\"",
19
+ "test:integration": "vitest run test/integration/YdbRealIntegration.test.ts",
18
20
  "build": "tsc -p tsconfig.json",
19
21
  "typecheck": "tsc -p tsconfig.json --noEmit",
20
22
  "dev": "tsx watch src/index.ts",
@@ -67,6 +69,7 @@
67
69
  "@eslint/js": "^9.39.1",
68
70
  "@types/express": "^5.0.3",
69
71
  "@types/node": "^24.9.1",
72
+ "@vitest/coverage-v8": "^4.0.12",
70
73
  "docsify-cli": "^4.4.4",
71
74
  "eslint": "^9.39.1",
72
75
  "husky": "^9.1.7",
@@ -76,4 +79,4 @@
76
79
  "typescript-eslint": "^8.47.0",
77
80
  "vitest": "^4.0.12"
78
81
  }
79
- }
82
+ }