ydb-qdrant 3.0.0 → 4.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.
- package/README.md +7 -3
- package/dist/SmokeTest.js +1 -1
- package/dist/config/env.d.ts +6 -0
- package/dist/config/env.js +17 -0
- package/dist/index.js +5 -2
- package/dist/indexing/IndexScheduler.js +6 -51
- package/dist/indexing/IndexScheduler.multi-table.d.ts +12 -0
- package/dist/indexing/IndexScheduler.multi-table.js +54 -0
- package/dist/indexing/IndexScheduler.one-table.d.ts +1 -0
- package/dist/indexing/IndexScheduler.one-table.js +4 -0
- package/dist/package/{Api.d.ts → api.d.ts} +3 -2
- package/dist/package/api.js +55 -0
- package/dist/repositories/collectionsRepo.d.ts +3 -2
- package/dist/repositories/collectionsRepo.js +27 -53
- package/dist/repositories/collectionsRepo.multi-table.d.ts +3 -0
- package/dist/repositories/collectionsRepo.multi-table.js +23 -0
- package/dist/repositories/collectionsRepo.one-table.d.ts +3 -0
- package/dist/repositories/collectionsRepo.one-table.js +25 -0
- package/dist/repositories/collectionsRepo.shared.d.ts +2 -0
- package/dist/repositories/collectionsRepo.shared.js +23 -0
- package/dist/repositories/pointsRepo.d.ts +3 -3
- package/dist/repositories/pointsRepo.js +15 -158
- package/dist/repositories/pointsRepo.multi-table.d.ts +12 -0
- package/dist/repositories/pointsRepo.multi-table.js +129 -0
- package/dist/repositories/pointsRepo.one-table.d.ts +12 -0
- package/dist/repositories/pointsRepo.one-table.js +111 -0
- package/dist/routes/collections.js +2 -1
- package/dist/routes/points.js +2 -1
- package/dist/services/CollectionService.d.ts +35 -0
- package/dist/services/CollectionService.js +85 -0
- package/dist/services/CollectionService.multi-table.d.ts +5 -0
- package/dist/services/CollectionService.multi-table.js +7 -0
- package/dist/services/CollectionService.one-table.d.ts +5 -0
- package/dist/services/CollectionService.one-table.js +9 -0
- package/dist/services/CollectionService.shared.d.ts +11 -0
- package/dist/services/CollectionService.shared.js +17 -0
- package/dist/services/PointsService.d.ts +23 -0
- package/dist/services/PointsService.js +128 -0
- package/dist/services/errors.d.ts +9 -0
- package/dist/services/errors.js +9 -0
- package/dist/utils/distance.d.ts +6 -0
- package/dist/utils/distance.js +28 -0
- package/dist/utils/normalization.d.ts +10 -0
- package/dist/utils/normalization.js +92 -0
- package/dist/utils/retry.d.ts +8 -0
- package/dist/utils/retry.js +28 -0
- package/dist/utils/tenant.d.ts +1 -0
- package/dist/utils/tenant.js +3 -0
- package/dist/ydb/schema.d.ts +2 -0
- package/dist/ydb/schema.js +27 -0
- package/package.json +4 -4
- package/dist/package/Api.js +0 -79
- package/dist/services/QdrantService.d.ts +0 -54
- package/dist/services/QdrantService.js +0 -313
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { UpsertPointsReq, SearchReq, DeletePointsReq } from "../types.js";
|
|
2
|
+
import { ensureMetaTable } from "../ydb/schema.js";
|
|
3
|
+
import { getCollectionMeta } from "../repositories/collectionsRepo.js";
|
|
4
|
+
import { deletePoints as repoDeletePoints, searchPoints as repoSearchPoints, upsertPoints as repoUpsertPoints, } from "../repositories/pointsRepo.js";
|
|
5
|
+
import { requestIndexBuild } from "../indexing/IndexScheduler.js";
|
|
6
|
+
import { logger } from "../logging/logger.js";
|
|
7
|
+
import { VECTOR_INDEX_BUILD_ENABLED } from "../config/env.js";
|
|
8
|
+
import { QdrantServiceError } from "./errors.js";
|
|
9
|
+
import { normalizeCollectionContext, resolvePointsTableAndUid, } from "./CollectionService.js";
|
|
10
|
+
import { normalizeSearchBodyForSearch, normalizeSearchBodyForQuery, } from "../utils/normalization.js";
|
|
11
|
+
let loggedIndexBuildDisabled = false;
|
|
12
|
+
export async function upsertPoints(ctx, body) {
|
|
13
|
+
await ensureMetaTable();
|
|
14
|
+
const normalized = normalizeCollectionContext(ctx);
|
|
15
|
+
const meta = await getCollectionMeta(normalized.metaKey);
|
|
16
|
+
if (!meta) {
|
|
17
|
+
throw new QdrantServiceError(404, {
|
|
18
|
+
status: "error",
|
|
19
|
+
error: "collection not found",
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
const parsed = UpsertPointsReq.safeParse(body);
|
|
23
|
+
if (!parsed.success) {
|
|
24
|
+
throw new QdrantServiceError(400, {
|
|
25
|
+
status: "error",
|
|
26
|
+
error: parsed.error.flatten(),
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
const { tableName, uid } = await resolvePointsTableAndUid(normalized, meta);
|
|
30
|
+
const upserted = await repoUpsertPoints(tableName, parsed.data.points, meta.dimension, uid);
|
|
31
|
+
if (VECTOR_INDEX_BUILD_ENABLED) {
|
|
32
|
+
requestIndexBuild(tableName, meta.dimension, meta.distance, meta.vectorType);
|
|
33
|
+
}
|
|
34
|
+
else if (!loggedIndexBuildDisabled) {
|
|
35
|
+
logger.info({ table: tableName }, "vector index building disabled by env; skipping automatic emb_idx rebuilds");
|
|
36
|
+
loggedIndexBuildDisabled = true;
|
|
37
|
+
}
|
|
38
|
+
return { upserted };
|
|
39
|
+
}
|
|
40
|
+
async function executeSearch(ctx, normalizedSearch, source) {
|
|
41
|
+
await ensureMetaTable();
|
|
42
|
+
const normalized = normalizeCollectionContext(ctx);
|
|
43
|
+
logger.info({ tenant: normalized.tenant, collection: normalized.collection }, `${source}: resolve collection meta`);
|
|
44
|
+
const meta = await getCollectionMeta(normalized.metaKey);
|
|
45
|
+
if (!meta) {
|
|
46
|
+
logger.warn({
|
|
47
|
+
tenant: normalized.tenant,
|
|
48
|
+
collection: normalized.collection,
|
|
49
|
+
metaKey: normalized.metaKey,
|
|
50
|
+
}, `${source}: collection not found`);
|
|
51
|
+
throw new QdrantServiceError(404, {
|
|
52
|
+
status: "error",
|
|
53
|
+
error: "collection not found",
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
const parsed = SearchReq.safeParse({
|
|
57
|
+
vector: normalizedSearch.vector,
|
|
58
|
+
top: normalizedSearch.top,
|
|
59
|
+
with_payload: normalizedSearch.withPayload,
|
|
60
|
+
});
|
|
61
|
+
if (!parsed.success) {
|
|
62
|
+
logger.warn({
|
|
63
|
+
tenant: normalized.tenant,
|
|
64
|
+
collection: normalized.collection,
|
|
65
|
+
issues: parsed.error.issues,
|
|
66
|
+
}, `${source}: invalid payload`);
|
|
67
|
+
throw new QdrantServiceError(400, {
|
|
68
|
+
status: "error",
|
|
69
|
+
error: parsed.error.flatten(),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
const { tableName, uid } = await resolvePointsTableAndUid(normalized, meta);
|
|
73
|
+
logger.info({
|
|
74
|
+
tenant: normalized.tenant,
|
|
75
|
+
collection: normalized.collection,
|
|
76
|
+
top: parsed.data.top,
|
|
77
|
+
queryVectorLen: parsed.data.vector.length,
|
|
78
|
+
collectionDim: meta.dimension,
|
|
79
|
+
distance: meta.distance,
|
|
80
|
+
vectorType: meta.vectorType,
|
|
81
|
+
}, `${source}: executing`);
|
|
82
|
+
const hits = await repoSearchPoints(tableName, parsed.data.vector, parsed.data.top, parsed.data.with_payload, meta.distance, meta.dimension, uid);
|
|
83
|
+
const threshold = normalizedSearch.scoreThreshold;
|
|
84
|
+
const filtered = threshold === undefined
|
|
85
|
+
? hits
|
|
86
|
+
: hits.filter((hit) => {
|
|
87
|
+
const isSimilarity = meta.distance === "Cosine" || meta.distance === "Dot";
|
|
88
|
+
if (isSimilarity) {
|
|
89
|
+
return hit.score >= threshold;
|
|
90
|
+
}
|
|
91
|
+
return hit.score <= threshold;
|
|
92
|
+
});
|
|
93
|
+
logger.info({
|
|
94
|
+
tenant: normalized.tenant,
|
|
95
|
+
collection: normalized.collection,
|
|
96
|
+
hits: hits.length,
|
|
97
|
+
}, `${source}: completed`);
|
|
98
|
+
return { points: filtered };
|
|
99
|
+
}
|
|
100
|
+
export async function searchPoints(ctx, body) {
|
|
101
|
+
const normalizedSearch = normalizeSearchBodyForSearch(body);
|
|
102
|
+
return await executeSearch(ctx, normalizedSearch, "search");
|
|
103
|
+
}
|
|
104
|
+
export async function queryPoints(ctx, body) {
|
|
105
|
+
const normalizedSearch = normalizeSearchBodyForQuery(body);
|
|
106
|
+
return await executeSearch(ctx, normalizedSearch, "query");
|
|
107
|
+
}
|
|
108
|
+
export async function deletePoints(ctx, body) {
|
|
109
|
+
await ensureMetaTable();
|
|
110
|
+
const normalized = normalizeCollectionContext(ctx);
|
|
111
|
+
const meta = await getCollectionMeta(normalized.metaKey);
|
|
112
|
+
if (!meta) {
|
|
113
|
+
throw new QdrantServiceError(404, {
|
|
114
|
+
status: "error",
|
|
115
|
+
error: "collection not found",
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
const parsed = DeletePointsReq.safeParse(body);
|
|
119
|
+
if (!parsed.success) {
|
|
120
|
+
throw new QdrantServiceError(400, {
|
|
121
|
+
status: "error",
|
|
122
|
+
error: parsed.error.flatten(),
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
const { tableName, uid } = await resolvePointsTableAndUid(normalized, meta);
|
|
126
|
+
const deleted = await repoDeletePoints(tableName, parsed.data.points, uid);
|
|
127
|
+
return { deleted };
|
|
128
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface QdrantServiceErrorPayload {
|
|
2
|
+
status: "error";
|
|
3
|
+
error: unknown;
|
|
4
|
+
}
|
|
5
|
+
export declare class QdrantServiceError extends Error {
|
|
6
|
+
readonly statusCode: number;
|
|
7
|
+
readonly payload: QdrantServiceErrorPayload;
|
|
8
|
+
constructor(statusCode: number, payload: QdrantServiceErrorPayload, message?: string);
|
|
9
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export function mapDistanceToKnnFn(distance) {
|
|
2
|
+
switch (distance) {
|
|
3
|
+
case "Cosine":
|
|
4
|
+
return { fn: "Knn::CosineSimilarity", order: "DESC" };
|
|
5
|
+
case "Dot":
|
|
6
|
+
return { fn: "Knn::InnerProductSimilarity", order: "DESC" };
|
|
7
|
+
case "Euclid":
|
|
8
|
+
return { fn: "Knn::EuclideanDistance", order: "ASC" };
|
|
9
|
+
case "Manhattan":
|
|
10
|
+
return { fn: "Knn::ManhattanDistance", order: "ASC" };
|
|
11
|
+
default:
|
|
12
|
+
return { fn: "Knn::CosineSimilarity", order: "DESC" };
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export function mapDistanceToIndexParam(distance) {
|
|
16
|
+
switch (distance) {
|
|
17
|
+
case "Cosine":
|
|
18
|
+
return "cosine";
|
|
19
|
+
case "Dot":
|
|
20
|
+
return "inner_product";
|
|
21
|
+
case "Euclid":
|
|
22
|
+
return "euclidean";
|
|
23
|
+
case "Manhattan":
|
|
24
|
+
return "manhattan";
|
|
25
|
+
default:
|
|
26
|
+
return "cosine";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface SearchNormalizationResult {
|
|
2
|
+
vector: number[] | undefined;
|
|
3
|
+
top: number | undefined;
|
|
4
|
+
withPayload: boolean | undefined;
|
|
5
|
+
scoreThreshold: number | undefined;
|
|
6
|
+
}
|
|
7
|
+
export declare function isNumberArray(value: unknown): value is number[];
|
|
8
|
+
export declare function extractVectorLoose(body: unknown, depth?: number): number[] | undefined;
|
|
9
|
+
export declare function normalizeSearchBodyForSearch(body: unknown): SearchNormalizationResult;
|
|
10
|
+
export declare function normalizeSearchBodyForQuery(body: unknown): SearchNormalizationResult;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
export function isNumberArray(value) {
|
|
2
|
+
return Array.isArray(value) && value.every((x) => typeof x === "number");
|
|
3
|
+
}
|
|
4
|
+
export function extractVectorLoose(body, depth = 0) {
|
|
5
|
+
if (!body || typeof body !== "object" || depth > 3) {
|
|
6
|
+
return undefined;
|
|
7
|
+
}
|
|
8
|
+
const obj = body;
|
|
9
|
+
if (isNumberArray(obj.vector))
|
|
10
|
+
return obj.vector;
|
|
11
|
+
if (isNumberArray(obj.embedding))
|
|
12
|
+
return obj.embedding;
|
|
13
|
+
const query = obj.query;
|
|
14
|
+
if (query) {
|
|
15
|
+
const queryVector = query["vector"];
|
|
16
|
+
if (isNumberArray(queryVector))
|
|
17
|
+
return queryVector;
|
|
18
|
+
const nearest = query["nearest"];
|
|
19
|
+
if (nearest && isNumberArray(nearest.vector)) {
|
|
20
|
+
return nearest.vector;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const nearest = obj.nearest;
|
|
24
|
+
if (nearest && isNumberArray(nearest.vector)) {
|
|
25
|
+
return nearest.vector;
|
|
26
|
+
}
|
|
27
|
+
for (const key of Object.keys(obj)) {
|
|
28
|
+
const value = obj[key];
|
|
29
|
+
if (isNumberArray(value)) {
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
for (const key of Object.keys(obj)) {
|
|
34
|
+
const value = obj[key];
|
|
35
|
+
if (value && typeof value === "object") {
|
|
36
|
+
const found = extractVectorLoose(value, depth + 1);
|
|
37
|
+
if (found) {
|
|
38
|
+
return found;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
export function normalizeSearchBodyForSearch(body) {
|
|
45
|
+
if (!body || typeof body !== "object") {
|
|
46
|
+
return {
|
|
47
|
+
vector: undefined,
|
|
48
|
+
top: undefined,
|
|
49
|
+
withPayload: undefined,
|
|
50
|
+
scoreThreshold: undefined,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const b = body;
|
|
54
|
+
const rawVector = b["vector"];
|
|
55
|
+
const vector = isNumberArray(rawVector) ? rawVector : undefined;
|
|
56
|
+
return normalizeSearchCommon(b, vector);
|
|
57
|
+
}
|
|
58
|
+
export function normalizeSearchBodyForQuery(body) {
|
|
59
|
+
if (!body || typeof body !== "object") {
|
|
60
|
+
return {
|
|
61
|
+
vector: undefined,
|
|
62
|
+
top: undefined,
|
|
63
|
+
withPayload: undefined,
|
|
64
|
+
scoreThreshold: undefined,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
const b = body;
|
|
68
|
+
const vector = extractVectorLoose(b);
|
|
69
|
+
return normalizeSearchCommon(b, vector);
|
|
70
|
+
}
|
|
71
|
+
function normalizeSearchCommon(b, vector) {
|
|
72
|
+
const rawTop = b["top"];
|
|
73
|
+
const rawLimit = b["limit"];
|
|
74
|
+
const topFromTop = typeof rawTop === "number" ? rawTop : undefined;
|
|
75
|
+
const topFromLimit = typeof rawLimit === "number" ? rawLimit : undefined;
|
|
76
|
+
const top = topFromTop ?? topFromLimit;
|
|
77
|
+
let withPayload;
|
|
78
|
+
const rawWithPayload = b["with_payload"];
|
|
79
|
+
if (typeof rawWithPayload === "boolean") {
|
|
80
|
+
withPayload = rawWithPayload;
|
|
81
|
+
}
|
|
82
|
+
else if (Array.isArray(rawWithPayload) ||
|
|
83
|
+
typeof rawWithPayload === "object") {
|
|
84
|
+
withPayload = true;
|
|
85
|
+
}
|
|
86
|
+
const thresholdRaw = b["score_threshold"];
|
|
87
|
+
const thresholdValue = typeof thresholdRaw === "number" ? thresholdRaw : Number(thresholdRaw);
|
|
88
|
+
const scoreThreshold = Number.isFinite(thresholdValue)
|
|
89
|
+
? thresholdValue
|
|
90
|
+
: undefined;
|
|
91
|
+
return { vector, top, withPayload, scoreThreshold };
|
|
92
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface RetryOptions {
|
|
2
|
+
maxRetries?: number;
|
|
3
|
+
baseDelayMs?: number;
|
|
4
|
+
isTransient?: (error: unknown) => boolean;
|
|
5
|
+
context?: Record<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
export declare function isTransientYdbError(error: unknown): boolean;
|
|
8
|
+
export declare function withRetry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { logger } from "../logging/logger.js";
|
|
2
|
+
const DEFAULT_MAX_RETRIES = 6;
|
|
3
|
+
const DEFAULT_BASE_DELAY_MS = 250;
|
|
4
|
+
export function isTransientYdbError(error) {
|
|
5
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
6
|
+
return /Aborted|schema version mismatch|Table metadata loading|Failed to load metadata/i.test(msg);
|
|
7
|
+
}
|
|
8
|
+
export async function withRetry(fn, options = {}) {
|
|
9
|
+
const maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
10
|
+
const baseDelayMs = options.baseDelayMs ?? DEFAULT_BASE_DELAY_MS;
|
|
11
|
+
const isTransient = options.isTransient ?? isTransientYdbError;
|
|
12
|
+
const context = options.context ?? {};
|
|
13
|
+
let attempt = 0;
|
|
14
|
+
while (true) {
|
|
15
|
+
try {
|
|
16
|
+
return await fn();
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
if (!isTransient(e) || attempt >= maxRetries) {
|
|
20
|
+
throw e;
|
|
21
|
+
}
|
|
22
|
+
const backoffMs = Math.floor(baseDelayMs * Math.pow(2, attempt) + Math.random() * 100);
|
|
23
|
+
logger.warn({ ...context, attempt, backoffMs }, "operation aborted due to transient error; retrying");
|
|
24
|
+
await new Promise((r) => setTimeout(r, backoffMs));
|
|
25
|
+
attempt += 1;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
package/dist/utils/tenant.d.ts
CHANGED
|
@@ -2,3 +2,4 @@ export declare function sanitizeCollectionName(name: string): string;
|
|
|
2
2
|
export declare function sanitizeTenantId(tenantId: string | undefined): string;
|
|
3
3
|
export declare function tableNameFor(tenantId: string, collection: string): string;
|
|
4
4
|
export declare function metaKeyFor(tenantId: string, collection: string): string;
|
|
5
|
+
export declare function uidFor(tenantId: string, collectionName: string): string;
|
package/dist/utils/tenant.js
CHANGED
|
@@ -15,3 +15,6 @@ export function tableNameFor(tenantId, collection) {
|
|
|
15
15
|
export function metaKeyFor(tenantId, collection) {
|
|
16
16
|
return `${sanitizeTenantId(tenantId)}/${sanitizeCollectionName(collection)}`;
|
|
17
17
|
}
|
|
18
|
+
export function uidFor(tenantId, collectionName) {
|
|
19
|
+
return tableNameFor(tenantId, collectionName);
|
|
20
|
+
}
|
package/dist/ydb/schema.d.ts
CHANGED
package/dist/ydb/schema.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { withSession, TableDescription, Column, Types } from "./client.js";
|
|
2
2
|
import { logger } from "../logging/logger.js";
|
|
3
|
+
export const GLOBAL_POINTS_TABLE = "qdrant_all_points";
|
|
4
|
+
let globalPointsTableReady = false;
|
|
3
5
|
export async function ensureMetaTable() {
|
|
4
6
|
try {
|
|
5
7
|
await withSession(async (s) => {
|
|
@@ -22,3 +24,28 @@ export async function ensureMetaTable() {
|
|
|
22
24
|
logger.debug({ err }, "ensureMetaTable: ignored");
|
|
23
25
|
}
|
|
24
26
|
}
|
|
27
|
+
export async function ensureGlobalPointsTable() {
|
|
28
|
+
if (globalPointsTableReady) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
await withSession(async (s) => {
|
|
33
|
+
try {
|
|
34
|
+
await s.describeTable(GLOBAL_POINTS_TABLE);
|
|
35
|
+
globalPointsTableReady = true;
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
const desc = new TableDescription()
|
|
40
|
+
.withColumns(new Column("uid", Types.UTF8), new Column("point_id", Types.UTF8), new Column("embedding", Types.BYTES), new Column("payload", Types.JSON_DOCUMENT))
|
|
41
|
+
.withPrimaryKeys("uid", "point_id");
|
|
42
|
+
await s.createTable(GLOBAL_POINTS_TABLE, desc);
|
|
43
|
+
globalPointsTableReady = true;
|
|
44
|
+
logger.info(`created global points table ${GLOBAL_POINTS_TABLE}`);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
logger.debug({ err }, "ensureGlobalPointsTable: ignored");
|
|
50
|
+
}
|
|
51
|
+
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ydb-qdrant",
|
|
3
|
-
"version": "
|
|
4
|
-
"main": "dist/package/
|
|
5
|
-
"types": "dist/package/
|
|
3
|
+
"version": "4.1.0",
|
|
4
|
+
"main": "dist/package/api.js",
|
|
5
|
+
"types": "dist/package/api.d.ts",
|
|
6
6
|
"exports": {
|
|
7
|
-
".": "./dist/package/
|
|
7
|
+
".": "./dist/package/api.js",
|
|
8
8
|
"./server": "./dist/server.js"
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
package/dist/package/Api.js
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { readyOrThrow, configureDriver } from "../ydb/client.js";
|
|
2
|
-
import { ensureMetaTable } from "../ydb/schema.js";
|
|
3
|
-
import { createCollection as serviceCreateCollection, deleteCollection as serviceDeleteCollection, getCollection as serviceGetCollection, putCollectionIndex as servicePutCollectionIndex, upsertPoints as serviceUpsertPoints, searchPoints as serviceSearchPoints, deletePoints as serviceDeletePoints, } from "../services/QdrantService.js";
|
|
4
|
-
export { QdrantServiceError } from "../services/QdrantService.js";
|
|
5
|
-
export { CreateCollectionReq, UpsertPointsReq, SearchReq, DeletePointsReq, } from "../types.js";
|
|
6
|
-
export async function createYdbQdrantClient(options = {}) {
|
|
7
|
-
if (options.endpoint !== undefined ||
|
|
8
|
-
options.database !== undefined ||
|
|
9
|
-
options.connectionString !== undefined ||
|
|
10
|
-
options.authService !== undefined) {
|
|
11
|
-
configureDriver({
|
|
12
|
-
endpoint: options.endpoint,
|
|
13
|
-
database: options.database,
|
|
14
|
-
connectionString: options.connectionString,
|
|
15
|
-
authService: options.authService,
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
await readyOrThrow();
|
|
19
|
-
await ensureMetaTable();
|
|
20
|
-
const defaultTenant = options.defaultTenant ?? "default";
|
|
21
|
-
const resolveTenant = (tenant) => tenant ?? defaultTenant;
|
|
22
|
-
const client = {
|
|
23
|
-
async createCollection(collection, body) {
|
|
24
|
-
const tenant = resolveTenant(undefined);
|
|
25
|
-
return await serviceCreateCollection({ tenant, collection }, body);
|
|
26
|
-
},
|
|
27
|
-
async getCollection(collection) {
|
|
28
|
-
const tenant = resolveTenant(undefined);
|
|
29
|
-
return await serviceGetCollection({ tenant, collection });
|
|
30
|
-
},
|
|
31
|
-
async deleteCollection(collection) {
|
|
32
|
-
const tenant = resolveTenant(undefined);
|
|
33
|
-
return await serviceDeleteCollection({ tenant, collection });
|
|
34
|
-
},
|
|
35
|
-
async putCollectionIndex(collection) {
|
|
36
|
-
const tenant = resolveTenant(undefined);
|
|
37
|
-
return await servicePutCollectionIndex({ tenant, collection });
|
|
38
|
-
},
|
|
39
|
-
async upsertPoints(collection, body) {
|
|
40
|
-
const tenant = resolveTenant(undefined);
|
|
41
|
-
return await serviceUpsertPoints({ tenant, collection }, body);
|
|
42
|
-
},
|
|
43
|
-
async searchPoints(collection, body) {
|
|
44
|
-
const tenant = resolveTenant(undefined);
|
|
45
|
-
return await serviceSearchPoints({ tenant, collection }, body);
|
|
46
|
-
},
|
|
47
|
-
async deletePoints(collection, body) {
|
|
48
|
-
const tenant = resolveTenant(undefined);
|
|
49
|
-
return await serviceDeletePoints({ tenant, collection }, body);
|
|
50
|
-
},
|
|
51
|
-
forTenant(tenantId) {
|
|
52
|
-
const tenant = tenantId;
|
|
53
|
-
return {
|
|
54
|
-
createCollection(collection, body) {
|
|
55
|
-
return serviceCreateCollection({ tenant, collection }, body);
|
|
56
|
-
},
|
|
57
|
-
getCollection(collection) {
|
|
58
|
-
return serviceGetCollection({ tenant, collection });
|
|
59
|
-
},
|
|
60
|
-
deleteCollection(collection) {
|
|
61
|
-
return serviceDeleteCollection({ tenant, collection });
|
|
62
|
-
},
|
|
63
|
-
putCollectionIndex(collection) {
|
|
64
|
-
return servicePutCollectionIndex({ tenant, collection });
|
|
65
|
-
},
|
|
66
|
-
upsertPoints(collection, body) {
|
|
67
|
-
return serviceUpsertPoints({ tenant, collection }, body);
|
|
68
|
-
},
|
|
69
|
-
searchPoints(collection, body) {
|
|
70
|
-
return serviceSearchPoints({ tenant, collection }, body);
|
|
71
|
-
},
|
|
72
|
-
deletePoints(collection, body) {
|
|
73
|
-
return serviceDeletePoints({ tenant, collection }, body);
|
|
74
|
-
},
|
|
75
|
-
};
|
|
76
|
-
},
|
|
77
|
-
};
|
|
78
|
-
return client;
|
|
79
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { type DistanceKind } from "../types.js";
|
|
2
|
-
export interface QdrantServiceErrorPayload {
|
|
3
|
-
status: "error";
|
|
4
|
-
error: unknown;
|
|
5
|
-
}
|
|
6
|
-
export declare class QdrantServiceError extends Error {
|
|
7
|
-
readonly statusCode: number;
|
|
8
|
-
readonly payload: QdrantServiceErrorPayload;
|
|
9
|
-
constructor(statusCode: number, payload: QdrantServiceErrorPayload, message?: string);
|
|
10
|
-
}
|
|
11
|
-
interface CollectionContextInput {
|
|
12
|
-
tenant: string | undefined;
|
|
13
|
-
collection: string;
|
|
14
|
-
}
|
|
15
|
-
export declare function putCollectionIndex(ctx: CollectionContextInput): Promise<{
|
|
16
|
-
acknowledged: boolean;
|
|
17
|
-
}>;
|
|
18
|
-
export declare function createCollection(ctx: CollectionContextInput, body: unknown): Promise<{
|
|
19
|
-
name: string;
|
|
20
|
-
tenant: string;
|
|
21
|
-
}>;
|
|
22
|
-
export declare function getCollection(ctx: CollectionContextInput): Promise<{
|
|
23
|
-
name: string;
|
|
24
|
-
vectors: {
|
|
25
|
-
size: number;
|
|
26
|
-
distance: DistanceKind;
|
|
27
|
-
data_type: string;
|
|
28
|
-
};
|
|
29
|
-
}>;
|
|
30
|
-
export declare function deleteCollection(ctx: CollectionContextInput): Promise<{
|
|
31
|
-
acknowledged: boolean;
|
|
32
|
-
}>;
|
|
33
|
-
type PointsContextInput = CollectionContextInput;
|
|
34
|
-
export declare function upsertPoints(ctx: PointsContextInput, body: unknown): Promise<{
|
|
35
|
-
upserted: number;
|
|
36
|
-
}>;
|
|
37
|
-
export declare function searchPoints(ctx: PointsContextInput, body: unknown): Promise<{
|
|
38
|
-
points: Array<{
|
|
39
|
-
id: string;
|
|
40
|
-
score: number;
|
|
41
|
-
payload?: Record<string, unknown>;
|
|
42
|
-
}>;
|
|
43
|
-
}>;
|
|
44
|
-
export declare function queryPoints(ctx: PointsContextInput, body: unknown): Promise<{
|
|
45
|
-
points: Array<{
|
|
46
|
-
id: string;
|
|
47
|
-
score: number;
|
|
48
|
-
payload?: Record<string, unknown>;
|
|
49
|
-
}>;
|
|
50
|
-
}>;
|
|
51
|
-
export declare function deletePoints(ctx: PointsContextInput, body: unknown): Promise<{
|
|
52
|
-
deleted: number;
|
|
53
|
-
}>;
|
|
54
|
-
export {};
|