ydb-qdrant 6.0.0 → 8.1.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.
Files changed (39) hide show
  1. package/dist/config/env.d.ts +0 -3
  2. package/dist/config/env.js +0 -17
  3. package/dist/package/api.d.ts +3 -0
  4. package/dist/qdrant/QdrantRestTypes.d.ts +35 -0
  5. package/dist/qdrant/QdrantRestTypes.js +1 -0
  6. package/dist/repositories/collectionsRepo.one-table.js +37 -63
  7. package/dist/repositories/collectionsRepo.shared.js +8 -2
  8. package/dist/repositories/pointsRepo.d.ts +5 -11
  9. package/dist/repositories/pointsRepo.js +6 -3
  10. package/dist/repositories/pointsRepo.one-table/Delete.d.ts +2 -0
  11. package/dist/repositories/pointsRepo.one-table/Delete.js +166 -0
  12. package/dist/repositories/pointsRepo.one-table/PathSegmentsFilter.d.ts +14 -0
  13. package/dist/repositories/pointsRepo.one-table/PathSegmentsFilter.js +33 -0
  14. package/dist/repositories/pointsRepo.one-table/Search.d.ts +4 -0
  15. package/dist/repositories/pointsRepo.one-table/Search.js +208 -0
  16. package/dist/repositories/pointsRepo.one-table/Upsert.d.ts +2 -0
  17. package/dist/repositories/pointsRepo.one-table/Upsert.js +85 -0
  18. package/dist/repositories/pointsRepo.one-table.d.ts +3 -13
  19. package/dist/repositories/pointsRepo.one-table.js +3 -403
  20. package/dist/routes/points.js +17 -4
  21. package/dist/server.d.ts +1 -0
  22. package/dist/server.js +70 -2
  23. package/dist/services/CollectionService.d.ts +9 -0
  24. package/dist/services/CollectionService.js +9 -0
  25. package/dist/services/PointsService.d.ts +3 -10
  26. package/dist/services/PointsService.js +73 -3
  27. package/dist/types.d.ts +59 -5
  28. package/dist/types.js +27 -3
  29. package/dist/utils/normalization.d.ts +1 -0
  30. package/dist/utils/normalization.js +2 -1
  31. package/dist/utils/vectorBinary.js +94 -10
  32. package/dist/ydb/bootstrapMetaTable.d.ts +7 -0
  33. package/dist/ydb/bootstrapMetaTable.js +75 -0
  34. package/dist/ydb/client.d.ts +10 -3
  35. package/dist/ydb/client.js +26 -2
  36. package/dist/ydb/helpers.d.ts +0 -2
  37. package/dist/ydb/helpers.js +0 -7
  38. package/dist/ydb/schema.js +100 -66
  39. package/package.json +3 -6
@@ -1,403 +1,3 @@
1
- import { TypedValues, Types, withSession, createExecuteQuerySettings, createExecuteQuerySettingsWithTimeout, } from "../ydb/client.js";
2
- import { buildVectorParam, buildVectorBinaryParams } from "../ydb/helpers.js";
3
- import { mapDistanceToKnnFn, mapDistanceToBitKnnFn, } from "../utils/distance.js";
4
- import { withRetry, isTransientYdbError } from "../utils/retry.js";
5
- import { UPSERT_BATCH_SIZE } from "../ydb/schema.js";
6
- import { CLIENT_SIDE_SERIALIZATION_ENABLED, SearchMode, UPSERT_OPERATION_TIMEOUT_MS, SEARCH_OPERATION_TIMEOUT_MS, } from "../config/env.js";
7
- import { logger } from "../logging/logger.js";
8
- export async function upsertPointsOneTable(tableName, points, dimension, uid) {
9
- for (const p of points) {
10
- const id = String(p.id);
11
- if (p.vector.length !== dimension) {
12
- const previewLength = Math.min(16, p.vector.length);
13
- const vectorPreview = previewLength > 0 ? p.vector.slice(0, previewLength) : [];
14
- logger.warn({
15
- tableName,
16
- uid,
17
- pointId: id,
18
- vectorLen: p.vector.length,
19
- expectedDimension: dimension,
20
- vectorPreview,
21
- }, "upsertPointsOneTable: vector dimension mismatch");
22
- throw new Error(`Vector dimension mismatch for id=${id}: got ${p.vector.length}, expected ${dimension}`);
23
- }
24
- }
25
- let upserted = 0;
26
- await withSession(async (s) => {
27
- const settings = createExecuteQuerySettingsWithTimeout({
28
- keepInCache: true,
29
- idempotent: true,
30
- timeoutMs: UPSERT_OPERATION_TIMEOUT_MS,
31
- });
32
- for (let i = 0; i < points.length; i += UPSERT_BATCH_SIZE) {
33
- const batch = points.slice(i, i + UPSERT_BATCH_SIZE);
34
- let ddl;
35
- let params;
36
- if (CLIENT_SIDE_SERIALIZATION_ENABLED) {
37
- ddl = `
38
- DECLARE $rows AS List<Struct<
39
- uid: Utf8,
40
- point_id: Utf8,
41
- embedding: String,
42
- embedding_quantized: String,
43
- payload: JsonDocument
44
- >>;
45
-
46
- UPSERT INTO ${tableName} (uid, point_id, embedding, embedding_quantized, payload)
47
- SELECT
48
- uid,
49
- point_id,
50
- embedding,
51
- embedding_quantized,
52
- payload
53
- FROM AS_TABLE($rows);
54
- `;
55
- const rowType = Types.struct({
56
- uid: Types.UTF8,
57
- point_id: Types.UTF8,
58
- embedding: Types.BYTES,
59
- embedding_quantized: Types.BYTES,
60
- payload: Types.JSON_DOCUMENT,
61
- });
62
- const rowsValue = TypedValues.list(rowType, batch.map((p) => {
63
- const binaries = buildVectorBinaryParams(p.vector);
64
- return {
65
- uid,
66
- point_id: String(p.id),
67
- embedding: binaries.float,
68
- embedding_quantized: binaries.bit,
69
- payload: JSON.stringify(p.payload ?? {}),
70
- };
71
- }));
72
- params = {
73
- $rows: rowsValue,
74
- };
75
- }
76
- else {
77
- ddl = `
78
- DECLARE $rows AS List<Struct<
79
- uid: Utf8,
80
- point_id: Utf8,
81
- vec: List<Float>,
82
- payload: JsonDocument
83
- >>;
84
-
85
- UPSERT INTO ${tableName} (uid, point_id, embedding, embedding_quantized, payload)
86
- SELECT
87
- uid,
88
- point_id,
89
- Untag(Knn::ToBinaryStringFloat(vec), "FloatVector") AS embedding,
90
- Untag(Knn::ToBinaryStringBit(vec), "BitVector") AS embedding_quantized,
91
- payload
92
- FROM AS_TABLE($rows);
93
- `;
94
- const rowType = Types.struct({
95
- uid: Types.UTF8,
96
- point_id: Types.UTF8,
97
- vec: Types.list(Types.FLOAT),
98
- payload: Types.JSON_DOCUMENT,
99
- });
100
- const rowsValue = TypedValues.list(rowType, batch.map((p) => ({
101
- uid,
102
- point_id: String(p.id),
103
- vec: p.vector,
104
- payload: JSON.stringify(p.payload ?? {}),
105
- })));
106
- params = {
107
- $rows: rowsValue,
108
- };
109
- }
110
- logger.debug({
111
- tableName,
112
- mode: CLIENT_SIDE_SERIALIZATION_ENABLED
113
- ? "one_table_upsert_client_side_serialization"
114
- : "one_table_upsert_server_side_knn",
115
- batchSize: batch.length,
116
- yql: ddl,
117
- params: {
118
- rows: batch.map((p) => ({
119
- uid,
120
- point_id: String(p.id),
121
- vectorLength: p.vector.length,
122
- vectorPreview: p.vector.slice(0, 3),
123
- payload: p.payload ?? {},
124
- })),
125
- },
126
- }, "one_table upsert: executing YQL");
127
- await withRetry(() => s.executeQuery(ddl, params, undefined, settings), {
128
- isTransient: isTransientYdbError,
129
- context: { tableName, batchSize: batch.length },
130
- });
131
- upserted += batch.length;
132
- }
133
- });
134
- return upserted;
135
- }
136
- async function searchPointsOneTableExact(tableName, queryVector, top, withPayload, distance, dimension, uid) {
137
- if (queryVector.length !== dimension) {
138
- throw new Error(`Vector dimension mismatch: got ${queryVector.length}, expected ${dimension}`);
139
- }
140
- const { fn, order } = mapDistanceToKnnFn(distance);
141
- const results = await withSession(async (s) => {
142
- let yql;
143
- let params;
144
- if (CLIENT_SIDE_SERIALIZATION_ENABLED) {
145
- const binaries = buildVectorBinaryParams(queryVector);
146
- yql = `
147
- DECLARE $qbinf AS String;
148
- DECLARE $k AS Uint32;
149
- DECLARE $uid AS Utf8;
150
- SELECT point_id, ${withPayload ? "payload, " : ""}${fn}(embedding, $qbinf) AS score
151
- FROM ${tableName}
152
- WHERE uid = $uid
153
- ORDER BY score ${order}
154
- LIMIT $k;
155
- `;
156
- params = {
157
- $qbinf: typeof TypedValues.bytes === "function"
158
- ? TypedValues.bytes(binaries.float)
159
- : binaries.float,
160
- $k: TypedValues.uint32(top),
161
- $uid: TypedValues.utf8(uid),
162
- };
163
- }
164
- else {
165
- const qf = buildVectorParam(queryVector);
166
- yql = `
167
- DECLARE $qf AS List<Float>;
168
- DECLARE $k AS Uint32;
169
- DECLARE $uid AS Utf8;
170
- $qbinf = Knn::ToBinaryStringFloat($qf);
171
- SELECT point_id, ${withPayload ? "payload, " : ""}${fn}(embedding, $qbinf) AS score
172
- FROM ${tableName}
173
- WHERE uid = $uid
174
- ORDER BY score ${order}
175
- LIMIT $k;
176
- `;
177
- params = {
178
- $qf: qf,
179
- $k: TypedValues.uint32(top),
180
- $uid: TypedValues.utf8(uid),
181
- };
182
- }
183
- logger.debug({
184
- tableName,
185
- distance,
186
- top,
187
- withPayload,
188
- mode: CLIENT_SIDE_SERIALIZATION_ENABLED
189
- ? "one_table_exact_client_side_serialization"
190
- : "one_table_exact",
191
- yql,
192
- params: {
193
- uid,
194
- top,
195
- vectorLength: queryVector.length,
196
- vectorPreview: queryVector.slice(0, 3),
197
- },
198
- }, "one_table search (exact): executing YQL");
199
- const settings = createExecuteQuerySettingsWithTimeout({
200
- keepInCache: true,
201
- idempotent: true,
202
- timeoutMs: SEARCH_OPERATION_TIMEOUT_MS,
203
- });
204
- const rs = await s.executeQuery(yql, params, undefined, settings);
205
- const rowset = rs.resultSets?.[0];
206
- const rows = (rowset?.rows ?? []);
207
- return rows.map((row) => {
208
- const id = row.items?.[0]?.textValue;
209
- if (typeof id !== "string") {
210
- throw new Error("point_id is missing in YDB search result");
211
- }
212
- let payload;
213
- let scoreIdx = 1;
214
- if (withPayload) {
215
- const payloadText = row.items?.[1]?.textValue;
216
- if (payloadText) {
217
- try {
218
- payload = JSON.parse(payloadText);
219
- }
220
- catch {
221
- payload = undefined;
222
- }
223
- }
224
- scoreIdx = 2;
225
- }
226
- const score = Number(row.items?.[scoreIdx]?.floatValue ?? row.items?.[scoreIdx]?.textValue);
227
- return { id, score, ...(payload ? { payload } : {}) };
228
- });
229
- });
230
- return results;
231
- }
232
- async function searchPointsOneTableApproximate(tableName, queryVector, top, withPayload, distance, dimension, uid, overfetchMultiplier) {
233
- if (queryVector.length !== dimension) {
234
- throw new Error(`Vector dimension mismatch: got ${queryVector.length}, expected ${dimension}`);
235
- }
236
- const { fn, order } = mapDistanceToKnnFn(distance);
237
- const { fn: bitFn, order: bitOrder } = mapDistanceToBitKnnFn(distance);
238
- const safeTop = top > 0 ? top : 1;
239
- const rawCandidateLimit = safeTop * overfetchMultiplier;
240
- const candidateLimit = Math.max(safeTop, rawCandidateLimit);
241
- const results = await withSession(async (s) => {
242
- let yql;
243
- let params;
244
- if (CLIENT_SIDE_SERIALIZATION_ENABLED) {
245
- const binaries = buildVectorBinaryParams(queryVector);
246
- yql = `
247
- DECLARE $qbin_bit AS String;
248
- DECLARE $qbinf AS String;
249
- DECLARE $candidateLimit AS Uint32;
250
- DECLARE $safeTop AS Uint32;
251
- DECLARE $uid AS Utf8;
252
-
253
- $candidates = (
254
- SELECT point_id
255
- FROM ${tableName}
256
- WHERE uid = $uid AND embedding_quantized IS NOT NULL
257
- ORDER BY ${bitFn}(embedding_quantized, $qbin_bit) ${bitOrder}
258
- LIMIT $candidateLimit
259
- );
260
-
261
- SELECT point_id, ${withPayload ? "payload, " : ""}${fn}(embedding, $qbinf) AS score
262
- FROM ${tableName}
263
- WHERE uid = $uid
264
- AND point_id IN $candidates
265
- ORDER BY score ${order}
266
- LIMIT $safeTop;
267
- `;
268
- params = {
269
- $qbin_bit: typeof TypedValues.bytes === "function"
270
- ? TypedValues.bytes(binaries.bit)
271
- : binaries.bit,
272
- $qbinf: typeof TypedValues.bytes === "function"
273
- ? TypedValues.bytes(binaries.float)
274
- : binaries.float,
275
- $candidateLimit: TypedValues.uint32(candidateLimit),
276
- $safeTop: TypedValues.uint32(safeTop),
277
- $uid: TypedValues.utf8(uid),
278
- };
279
- logger.debug({
280
- tableName,
281
- distance,
282
- top,
283
- safeTop,
284
- candidateLimit,
285
- mode: "one_table_approximate_client_side_serialization",
286
- yql,
287
- params: {
288
- uid,
289
- safeTop,
290
- candidateLimit,
291
- vectorLength: queryVector.length,
292
- vectorPreview: queryVector.slice(0, 3),
293
- },
294
- }, "one_table search (approximate): executing YQL with client-side serialization");
295
- }
296
- else {
297
- const qf = buildVectorParam(queryVector);
298
- yql = `
299
- DECLARE $qf AS List<Float>;
300
- DECLARE $candidateLimit AS Uint32;
301
- DECLARE $safeTop AS Uint32;
302
- DECLARE $uid AS Utf8;
303
-
304
- $qbin_bit = Knn::ToBinaryStringBit($qf);
305
- $qbinf = Knn::ToBinaryStringFloat($qf);
306
-
307
- $candidates = (
308
- SELECT point_id
309
- FROM ${tableName}
310
- WHERE uid = $uid AND embedding_quantized IS NOT NULL
311
- ORDER BY ${bitFn}(embedding_quantized, $qbin_bit) ${bitOrder}
312
- LIMIT $candidateLimit
313
- );
314
-
315
- SELECT point_id, ${withPayload ? "payload, " : ""}${fn}(embedding, $qbinf) AS score
316
- FROM ${tableName}
317
- WHERE uid = $uid
318
- AND point_id IN $candidates
319
- ORDER BY score ${order}
320
- LIMIT $safeTop;
321
- `;
322
- params = {
323
- $qf: qf,
324
- $candidateLimit: TypedValues.uint32(candidateLimit),
325
- $safeTop: TypedValues.uint32(safeTop),
326
- $uid: TypedValues.utf8(uid),
327
- };
328
- logger.debug({
329
- tableName,
330
- distance,
331
- top,
332
- safeTop,
333
- candidateLimit,
334
- mode: "one_table_approximate",
335
- yql,
336
- params: {
337
- uid,
338
- safeTop,
339
- candidateLimit,
340
- vectorLength: queryVector.length,
341
- vectorPreview: queryVector.slice(0, 3),
342
- },
343
- }, "one_table search (approximate): executing YQL");
344
- }
345
- const settings = createExecuteQuerySettingsWithTimeout({
346
- keepInCache: true,
347
- idempotent: true,
348
- timeoutMs: SEARCH_OPERATION_TIMEOUT_MS,
349
- });
350
- const rs = await s.executeQuery(yql, params, undefined, settings);
351
- const rowset = rs.resultSets?.[0];
352
- const rows = (rowset?.rows ?? []);
353
- return rows.map((row) => {
354
- const id = row.items?.[0]?.textValue;
355
- if (typeof id !== "string") {
356
- throw new Error("point_id is missing in YDB search result");
357
- }
358
- let payload;
359
- let scoreIdx = 1;
360
- if (withPayload) {
361
- const payloadText = row.items?.[1]?.textValue;
362
- if (payloadText) {
363
- try {
364
- payload = JSON.parse(payloadText);
365
- }
366
- catch {
367
- payload = undefined;
368
- }
369
- }
370
- scoreIdx = 2;
371
- }
372
- const score = Number(row.items?.[scoreIdx]?.floatValue ?? row.items?.[scoreIdx]?.textValue);
373
- return { id, score, ...(payload ? { payload } : {}) };
374
- });
375
- });
376
- return results;
377
- }
378
- export async function searchPointsOneTable(tableName, queryVector, top, withPayload, distance, dimension, uid, mode, overfetchMultiplier) {
379
- if (mode === SearchMode.Exact) {
380
- return await searchPointsOneTableExact(tableName, queryVector, top, withPayload, distance, dimension, uid);
381
- }
382
- return await searchPointsOneTableApproximate(tableName, queryVector, top, withPayload, distance, dimension, uid, overfetchMultiplier);
383
- }
384
- export async function deletePointsOneTable(tableName, ids, uid) {
385
- let deleted = 0;
386
- await withSession(async (s) => {
387
- const settings = createExecuteQuerySettings();
388
- for (const id of ids) {
389
- const yql = `
390
- DECLARE $uid AS Utf8;
391
- DECLARE $id AS Utf8;
392
- DELETE FROM ${tableName} WHERE uid = $uid AND point_id = $id;
393
- `;
394
- const params = {
395
- $uid: TypedValues.utf8(uid),
396
- $id: TypedValues.utf8(String(id)),
397
- };
398
- await s.executeQuery(yql, params, undefined, settings);
399
- deleted += 1;
400
- }
401
- });
402
- return deleted;
403
- }
1
+ export { searchPointsOneTable } from "./pointsRepo.one-table/Search.js";
2
+ export { upsertPointsOneTable } from "./pointsRepo.one-table/Upsert.js";
3
+ export { deletePointsOneTable, deletePointsByPathSegmentsOneTable, } from "./pointsRepo.one-table/Delete.js";
@@ -5,6 +5,19 @@ import { logger } from "../logging/logger.js";
5
5
  import { isCompilationTimeoutError } from "../ydb/client.js";
6
6
  import { scheduleExit } from "../utils/exit.js";
7
7
  export const pointsRouter = Router();
8
+ function toQdrantScoredPoint(p) {
9
+ // We don't currently track per-point versions or return vectors/shard keys,
10
+ // but many Qdrant clients expect these fields to exist in the response.
11
+ return {
12
+ id: p.id,
13
+ version: 0,
14
+ score: p.score,
15
+ payload: p.payload ?? null,
16
+ vector: null,
17
+ shard_key: null,
18
+ order_value: null,
19
+ };
20
+ }
8
21
  // Qdrant-compatible: PUT /collections/:collection/points (upsert)
9
22
  pointsRouter.put("/:collection/points", async (req, res) => {
10
23
  try {
@@ -58,13 +71,13 @@ pointsRouter.post("/:collection/points/upsert", async (req, res) => {
58
71
  });
59
72
  pointsRouter.post("/:collection/points/search", async (req, res) => {
60
73
  try {
61
- const result = await searchPoints({
74
+ const { points } = await searchPoints({
62
75
  tenant: req.header("X-Tenant-Id") ?? undefined,
63
76
  collection: String(req.params.collection),
64
77
  apiKey: req.header("api-key") ?? undefined,
65
78
  userAgent: req.header("User-Agent") ?? undefined,
66
79
  }, req.body);
67
- res.json({ status: "ok", result });
80
+ res.json({ status: "ok", result: points.map(toQdrantScoredPoint) });
68
81
  }
69
82
  catch (err) {
70
83
  if (err instanceof QdrantServiceError) {
@@ -84,13 +97,13 @@ pointsRouter.post("/:collection/points/search", async (req, res) => {
84
97
  // Compatibility: some clients call POST /collections/:collection/points/query
85
98
  pointsRouter.post("/:collection/points/query", async (req, res) => {
86
99
  try {
87
- const result = await queryPoints({
100
+ const { points } = await queryPoints({
88
101
  tenant: req.header("X-Tenant-Id") ?? undefined,
89
102
  collection: String(req.params.collection),
90
103
  apiKey: req.header("api-key") ?? undefined,
91
104
  userAgent: req.header("User-Agent") ?? undefined,
92
105
  }, req.body);
93
- res.json({ status: "ok", result });
106
+ res.json({ status: "ok", result: points.map(toQdrantScoredPoint) });
94
107
  }
95
108
  catch (err) {
96
109
  if (err instanceof QdrantServiceError) {
package/dist/server.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  import type { Request, Response } from "express";
2
2
  export declare function healthHandler(_req: Request, res: Response): Promise<void>;
3
+ export declare function rootHandler(_req: Request, res: Response): void;
3
4
  export declare function buildServer(): import("express-serve-static-core").Express;
package/dist/server.js CHANGED
@@ -22,18 +22,86 @@ export async function healthHandler(_req, res) {
22
22
  logger.error({ err }, isTimeout
23
23
  ? "YDB compilation timeout during health probe; scheduling process exit"
24
24
  : "YDB health probe failed; scheduling process exit");
25
- res.status(503).json({ status: "error", error: "YDB health probe failed" });
25
+ res.status(503).json({
26
+ status: "error",
27
+ error: "YDB health probe failed",
28
+ });
26
29
  scheduleExit(1);
27
30
  return;
28
31
  }
29
32
  res.json({ status: "ok" });
30
33
  }
34
+ export function rootHandler(_req, res) {
35
+ const version = process.env.npm_package_version ?? "unknown";
36
+ res.json({ title: "ydb-qdrant", version });
37
+ }
31
38
  export function buildServer() {
32
39
  const app = express();
33
- app.use(express.json({ limit: "20mb" }));
34
40
  app.use(requestLogger);
41
+ app.use(express.json({ limit: "20mb" }));
42
+ app.get("/", rootHandler);
35
43
  app.get("/health", healthHandler);
36
44
  app.use("/collections", collectionsRouter);
37
45
  app.use("/collections", pointsRouter);
46
+ app.use((err, req, res, next) => {
47
+ if (!isRequestAbortedError(err)) {
48
+ next(err);
49
+ return;
50
+ }
51
+ // Client closed the connection while the request body was being read.
52
+ // Avoid Express default handler printing a stacktrace to stderr.
53
+ if (res.headersSent || res.writableEnded) {
54
+ return;
55
+ }
56
+ res.status(400).json({ status: "error", error: "request aborted" });
57
+ });
58
+ // Catch-all error handler: avoid Express default handler printing stacktraces to stderr
59
+ // and provide consistent JSON error responses.
60
+ app.use((err, _req, res, _next) => {
61
+ logger.error({ err }, "Unhandled error in Express middleware");
62
+ void _next;
63
+ if (res.headersSent || res.writableEnded) {
64
+ return;
65
+ }
66
+ const statusCode = extractHttpStatusCode(err) ?? 500;
67
+ const errorMessage = err instanceof Error ? err.message : String(err);
68
+ res.status(statusCode).json({
69
+ status: "error",
70
+ error: errorMessage,
71
+ });
72
+ });
38
73
  return app;
39
74
  }
75
+ function isRequestAbortedError(err) {
76
+ if (!err || typeof err !== "object") {
77
+ return false;
78
+ }
79
+ const typeValue = "type" in err && typeof err.type === "string" ? err.type : undefined;
80
+ if (typeValue === "request.aborted") {
81
+ return true;
82
+ }
83
+ if ("message" in err && typeof err.message === "string") {
84
+ return err.message.includes("request aborted");
85
+ }
86
+ return false;
87
+ }
88
+ function extractHttpStatusCode(err) {
89
+ if (!err || typeof err !== "object") {
90
+ return undefined;
91
+ }
92
+ const obj = err;
93
+ let statusCodeValue;
94
+ if (typeof obj.statusCode === "number") {
95
+ statusCodeValue = obj.statusCode;
96
+ }
97
+ else if (typeof obj.status === "number") {
98
+ statusCodeValue = obj.status;
99
+ }
100
+ if (statusCodeValue === undefined ||
101
+ !Number.isInteger(statusCodeValue) ||
102
+ statusCodeValue < 400 ||
103
+ statusCodeValue > 599) {
104
+ return undefined;
105
+ }
106
+ return statusCodeValue;
107
+ }
@@ -24,6 +24,15 @@ export declare function getCollection(ctx: CollectionContextInput): Promise<{
24
24
  distance: DistanceKind;
25
25
  data_type: string;
26
26
  };
27
+ config: {
28
+ params: {
29
+ vectors: {
30
+ size: number;
31
+ distance: DistanceKind;
32
+ data_type: string;
33
+ };
34
+ };
35
+ };
27
36
  }>;
28
37
  export declare function deleteCollection(ctx: CollectionContextInput): Promise<{
29
38
  acknowledged: boolean;
@@ -64,6 +64,15 @@ export async function getCollection(ctx) {
64
64
  distance: meta.distance,
65
65
  data_type: meta.vectorType,
66
66
  },
67
+ config: {
68
+ params: {
69
+ vectors: {
70
+ size: meta.dimension,
71
+ distance: meta.distance,
72
+ data_type: meta.vectorType,
73
+ },
74
+ },
75
+ },
67
76
  };
68
77
  }
69
78
  export async function deleteCollection(ctx) {
@@ -1,21 +1,14 @@
1
1
  import { type CollectionContextInput } from "./CollectionService.js";
2
+ import type { YdbQdrantScoredPoint } from "../qdrant/QdrantRestTypes.js";
2
3
  type PointsContextInput = CollectionContextInput;
3
4
  export declare function upsertPoints(ctx: PointsContextInput, body: unknown): Promise<{
4
5
  upserted: number;
5
6
  }>;
6
7
  export declare function searchPoints(ctx: PointsContextInput, body: unknown): Promise<{
7
- points: Array<{
8
- id: string;
9
- score: number;
10
- payload?: Record<string, unknown>;
11
- }>;
8
+ points: YdbQdrantScoredPoint[];
12
9
  }>;
13
10
  export declare function queryPoints(ctx: PointsContextInput, body: unknown): Promise<{
14
- points: Array<{
15
- id: string;
16
- score: number;
17
- payload?: Record<string, unknown>;
18
- }>;
11
+ points: YdbQdrantScoredPoint[];
19
12
  }>;
20
13
  export declare function deletePoints(ctx: PointsContextInput, body: unknown): Promise<{
21
14
  deleted: number;