From c30c769cdccc8054120da9311183ebba9aa991fd Mon Sep 17 00:00:00 2001 From: Ivan Pleshkov Date: Sun, 3 Mar 2024 17:19:37 +0000 Subject: [PATCH 1/6] v1.8.0 rest api update --- .../js-client-rest/src/api/collections-api.ts | 13 +- .../js-client-rest/src/api/service-api.ts | 5 + .../js-client-rest/src/api/snapshots-api.ts | 6 +- .../src/openapi/generated_schema.ts | 242 ++++++++++++++++-- packages/js-client-rest/src/qdrant-client.ts | 35 ++- 5 files changed, 272 insertions(+), 29 deletions(-) diff --git a/packages/js-client-rest/src/api/collections-api.ts b/packages/js-client-rest/src/api/collections-api.ts index c5cbc09..1789d75 100644 --- a/packages/js-client-rest/src/api/collections-api.ts +++ b/packages/js-client-rest/src/api/collections-api.ts @@ -66,6 +66,11 @@ export function createCollectionsApi(client: Client) { */ getCollectionsAliases: client.path('/aliases').method('get').create(), + /** + * Check the existence of a collection + */ + collectionExists: client.path('/collections/{collection_name}/exists').method('get').create(), + /** * Download specified snapshot from a collection as a file * @todo Fetcher needs to handle Blob for file downloads @@ -77,14 +82,6 @@ export function createCollectionsApi(client: Client) { */ listSnapshots: client.path('/collections/{collection_name}/snapshots').method('get').create(), - /** - * Recover local collection data from a snapshot. This will overwrite any data, stored on this node, for the collection. If collection does not exist - it will be created. - */ - recoverFromSnapshot: client - .path('/collections/{collection_name}/snapshots/recover') - .method('put') - .create({wait: true}), - updateAliases: client.path('/collections/aliases').method('post').create({timeout: true}), /** diff --git a/packages/js-client-rest/src/api/service-api.ts b/packages/js-client-rest/src/api/service-api.ts index f12d13c..a845187 100644 --- a/packages/js-client-rest/src/api/service-api.ts +++ b/packages/js-client-rest/src/api/service-api.ts @@ -36,5 +36,10 @@ export function createServiceApi(client: Client) { * An endpoint for health checking used in Kubernetes. */ readyz: client.path('/readyz').method('get').create(), + + /** + * Returns information about the running Qdrant instance. + */ + root: client.path('/').method('get').create(), } as const; } diff --git a/packages/js-client-rest/src/api/snapshots-api.ts b/packages/js-client-rest/src/api/snapshots-api.ts index 5fb88a0..5cd50de 100644 --- a/packages/js-client-rest/src/api/snapshots-api.ts +++ b/packages/js-client-rest/src/api/snapshots-api.ts @@ -53,7 +53,7 @@ export function createSnapshotsApi(client: Client) { recoverFromSnapshot: client .path('/collections/{collection_name}/snapshots/recover') .method('put') - .create({wait: true}), + .create({wait: true, checksum: true}), /** * Recover shard of a local collection from an uploaded snapshot. This will overwrite any data, stored on this node, for the collection shard @@ -61,7 +61,7 @@ export function createSnapshotsApi(client: Client) { recoverShardFromUploadedSnapshot: client .path('/collections/{collection_name}/shards/{shard_id}/snapshots/upload') .method('post') - .create({wait: true, priority: true}), + .create({wait: true, priority: true, checksum: true}), /** * Recover shard of a local collection data from a snapshot. This will overwrite any data, stored in this shard, for the collection @@ -69,7 +69,7 @@ export function createSnapshotsApi(client: Client) { recoverShardFromSnapshot: client .path('/collections/{collection_name}/shards/{shard_id}/snapshots/recover') .method('put') - .create({wait: true}), + .create({wait: true, checksum: true}), /** * Get list of snapshots for a shard of a collection diff --git a/packages/js-client-rest/src/openapi/generated_schema.ts b/packages/js-client-rest/src/openapi/generated_schema.ts index 46ee03d..a409d2f 100644 --- a/packages/js-client-rest/src/openapi/generated_schema.ts +++ b/packages/js-client-rest/src/openapi/generated_schema.ts @@ -18,6 +18,13 @@ export interface paths { /** Delete shard key */ post: operations["delete_shard_key"]; }; + "/": { + /** + * Returns information about the running Qdrant instance + * @description Returns information about the running Qdrant instance like version and commit id + */ + get: operations["root"]; + }; "/telemetry": { /** * Collect telemetry data @@ -123,6 +130,13 @@ export interface paths { */ put: operations["create_field_index"]; }; + "/collections/{collection_name}/exists": { + /** + * Check the existence of a collection + * @description Returns "true" if the given collection name exists, and "false" otherwise + */ + get: operations["collection_exists"]; + }; "/collections/{collection_name}/index/{field_name}": { /** * Delete index for field in collection @@ -557,7 +571,7 @@ export interface components { full_scan_threshold?: number | null; /** * Format: uint - * @description Number of parallel threads used for background index building. If 0 - auto selection. + * @description Number of parallel threads used for background index building. If 0 - automatically select from 8 to 16. Best to keep between 8 and 16 to prevent likelihood of building broken/inefficient HNSW graphs. On small CPUs, less threads are used. */ max_indexing_threads?: number | null; /** @description Store HNSW index on disk. If set to false, the index will be stored in RAM. Default: false */ @@ -637,7 +651,7 @@ export interface components { full_scan_threshold: number; /** * Format: uint - * @description Number of parallel threads used for background index building. If 0 - auto selection. + * @description Number of parallel threads used for background index building. If 0 - automatically select from 8 to 16. Best to keep between 8 and 16 to prevent likelihood of slow building or broken/inefficient HNSW graphs. On small CPUs, less threads are used. * @default 0 */ max_indexing_threads?: number; @@ -706,9 +720,10 @@ export interface components { flush_interval_sec: number; /** * Format: uint - * @description Maximum available threads for optimization workers + * @description Max number of threads (jobs) for running optimizations per shard. Note: each optimization job will also use `max_indexing_threads` threads by itself for index building. If null - have no limit and choose dynamically to saturate CPU. If 0 - no optimization threads, optimizations will be disabled. + * @default null */ - max_optimization_threads: number; + max_optimization_threads?: number | null; }; WalConfig: { /** @@ -736,9 +751,9 @@ export interface components { * @description All possible names of payload types * @enum {string} */ - PayloadSchemaType: "keyword" | "integer" | "float" | "geo" | "text" | "bool"; + PayloadSchemaType: "keyword" | "integer" | "float" | "geo" | "text" | "bool" | "datetime"; /** @description Payload type with parameters */ - PayloadSchemaParams: components["schemas"]["TextIndexParams"]; + PayloadSchemaParams: components["schemas"]["TextIndexParams"] | components["schemas"]["IntegerIndexParams"]; TextIndexParams: { type: components["schemas"]["TextIndexType"]; tokenizer?: components["schemas"]["TokenizerType"]; @@ -753,6 +768,15 @@ export interface components { TextIndexType: "text"; /** @enum {string} */ TokenizerType: "prefix" | "whitespace" | "word" | "multilingual"; + IntegerIndexParams: { + type: components["schemas"]["IntegerIndexType"]; + /** @description If true - support direct lookups. */ + lookup: boolean; + /** @description If true - support ranges filters. */ + range: boolean; + }; + /** @enum {string} */ + IntegerIndexType: "integer"; PointRequest: { /** @description Specify in which shards to look for the points, if not specified - look in all shards */ shard_key?: components["schemas"]["ShardKeySelector"] | (Record | null); @@ -863,6 +887,8 @@ export interface components { Filter: { /** @description At least one of those conditions should match */ should?: (components["schemas"]["Condition"])[] | null; + /** @description At least minimum amount of given conditions should match */ + min_should?: components["schemas"]["MinShould"] | (Record | null); /** @description All conditions must match */ must?: (components["schemas"]["Condition"])[] | null; /** @description All conditions must NOT match */ @@ -876,7 +902,7 @@ export interface components { /** @description Check if point has field with a given value */ match?: components["schemas"]["Match"] | (Record | null); /** @description Check if points value lies in a given range */ - range?: components["schemas"]["Range"] | (Record | null); + range?: components["schemas"]["RangeInterface"] | (Record | null); /** @description Check if points geo location lies in a given area */ geo_bounding_box?: components["schemas"]["GeoBoundingBox"] | (Record | null); /** @description Check if geo point is within a given radius */ @@ -906,6 +932,7 @@ export interface components { MatchExcept: { except: components["schemas"]["AnyVariants"]; }; + RangeInterface: components["schemas"]["Range"] | components["schemas"]["DatetimeRange"]; /** @description Range filter request */ Range: { /** @@ -929,6 +956,29 @@ export interface components { */ lte?: number | null; }; + /** @description Range filter request */ + DatetimeRange: { + /** + * Format: date-time + * @description point.key < range.lt + */ + lt?: string | null; + /** + * Format: date-time + * @description point.key > range.gt + */ + gt?: string | null; + /** + * Format: date-time + * @description point.key >= range.gte + */ + gte?: string | null; + /** + * Format: date-time + * @description point.key <= range.lte + */ + lte?: string | null; + }; /** * @description Geo filter request * @@ -1020,6 +1070,11 @@ export interface components { key: string; filter: components["schemas"]["Filter"]; }; + MinShould: { + conditions: (components["schemas"]["Condition"])[]; + /** Format: uint */ + min_count: number; + }; /** @description Additional parameters of the search */ SearchParams: { /** @@ -1195,7 +1250,21 @@ export interface components { /** @description Select which payload to return with the response. Default: All */ with_payload?: components["schemas"]["WithPayloadInterface"] | (Record | null); with_vector?: components["schemas"]["WithVector"]; + /** @description Order the records by a payload field. */ + order_by?: components["schemas"]["OrderByInterface"] | (Record | null); + }; + OrderByInterface: string | components["schemas"]["OrderBy"]; + OrderBy: { + /** @description Payload key to order by */ + key: string; + /** @description Direction of ordering: `asc` or `desc`. Default is ascending. */ + direction?: components["schemas"]["Direction"] | (Record | null); + /** @description Which payload value to start scrolling from. Default is the lowest value for `asc` and the highest for `desc` */ + start_from?: components["schemas"]["StartFrom"] | (Record | null); }; + /** @enum {string} */ + Direction: "asc" | "desc"; + StartFrom: number | string; /** @description Result of the points read request */ ScrollResult: { /** @description List of retrieved points */ @@ -1321,7 +1390,7 @@ export interface components { flush_interval_sec?: number | null; /** * Format: uint - * @description Maximum available threads for optimization workers + * @description Max number of threads (jobs) for running optimizations per shard. Note: each optimization job will also use `max_indexing_threads` threads by itself for index building. If null - have no limit and choose dynamically to saturate CPU. If 0 - no optimization threads, optimizations will be disabled. */ max_optimization_threads?: number | null; }; @@ -1467,6 +1536,8 @@ export interface components { /** @description Assigns payload to each point that satisfy this filter condition */ filter?: components["schemas"]["Filter"] | (Record | null); shard_key?: components["schemas"]["ShardKeySelector"] | (Record | null); + /** @description Assigns payload to each point that satisfy this path of property */ + key?: string | null; }; /** @description This data structure is used in API interface and applied across multiple shards */ DeletePayload: { @@ -1556,6 +1627,11 @@ export interface components { /** Format: uint */ count: number; latest_error?: string | null; + /** + * Format: date-time + * @description Timestamp of the latest error + */ + latest_error_timestamp?: string | null; }; SnapshotDescription: { name: string; @@ -1563,6 +1639,7 @@ export interface components { creation_time?: string | null; /** Format: uint64 */ size: number; + checksum?: string | null; }; /** @description Count Request Counts the number of points which satisfy the given filter. If filter is not provided, the count of all points in the collection will be returned. */ CountRequest: { @@ -1621,7 +1698,7 @@ export interface components { * @description State of the single shard within a replica set. * @enum {string} */ - ReplicaState: "Active" | "Dead" | "Partial" | "Initializing" | "Listener" | "PartialSnapshot"; + ReplicaState: "Active" | "Dead" | "Partial" | "Initializing" | "Listener" | "PartialSnapshot" | "Recovery"; RemoteShardInfo: { /** * Format: uint32 @@ -1640,13 +1717,21 @@ export interface components { ShardTransferInfo: { /** Format: uint32 */ shard_id: number; - /** Format: uint64 */ + /** + * Format: uint64 + * @description Source peer id + */ from: number; - /** Format: uint64 */ + /** + * Format: uint64 + * @description Destination peer id + */ to: number; /** @description If `true` transfer is a synchronization of a replicas If `false` transfer is a moving of a shard from one peer to another */ sync: boolean; method?: components["schemas"]["ShardTransferMethod"] | (Record | null); + /** @description A human-readable report of the transfer progress. Available only on the source peer. */ + comment?: string | null; }; /** @description Methods for transferring a shard from one node to another. */ ShardTransferMethod: "stream_records" | "snapshot"; @@ -1830,12 +1915,26 @@ export interface components { count: number; /** Format: uint */ fail_count?: number; - /** Format: float */ + /** + * Format: float + * @description The average time taken by 128 latest operations, calculated as a weighted mean. + */ avg_duration_micros?: number | null; - /** Format: float */ + /** + * Format: float + * @description The minimum duration of the operations across all the measurements. + */ min_duration_micros?: number | null; - /** Format: float */ + /** + * Format: float + * @description The maximum duration of the operations across all the measurements. + */ max_duration_micros?: number | null; + /** + * Format: uint64 + * @description The total duration of all operations in microseconds. + */ + total_duration_micros: number; /** Format: date-time */ last_responded?: string | null; }; @@ -1945,7 +2044,7 @@ export interface components { [key: string]: components["schemas"]["OperationDurationStatistics"] | undefined; }; }; - ClusterOperations: components["schemas"]["MoveShardOperation"] | components["schemas"]["ReplicateShardOperation"] | components["schemas"]["AbortTransferOperation"] | components["schemas"]["DropReplicaOperation"] | components["schemas"]["CreateShardingKeyOperation"] | components["schemas"]["DropShardingKeyOperation"]; + ClusterOperations: components["schemas"]["MoveShardOperation"] | components["schemas"]["ReplicateShardOperation"] | components["schemas"]["AbortTransferOperation"] | components["schemas"]["DropReplicaOperation"] | components["schemas"]["CreateShardingKeyOperation"] | components["schemas"]["DropShardingKeyOperation"] | components["schemas"]["RestartTransferOperation"]; MoveShardOperation: { move_shard: components["schemas"]["MoveShard"]; }; @@ -1998,6 +2097,18 @@ export interface components { DropShardingKey: { shard_key: components["schemas"]["ShardKey"]; }; + RestartTransferOperation: { + restart_transfer: components["schemas"]["RestartTransfer"]; + }; + RestartTransfer: { + /** Format: uint32 */ + shard_id: number; + /** Format: uint64 */ + from_peer_id: number; + /** Format: uint64 */ + to_peer_id: number; + method: components["schemas"]["ShardTransferMethod"]; + }; SearchRequestBatch: { searches: (components["schemas"]["SearchRequest"])[]; }; @@ -2019,6 +2130,11 @@ export interface components { * @default null */ priority?: components["schemas"]["SnapshotPriority"] | (Record | null); + /** + * @description Optional SHA256 checksum to verify snapshot integrity before recovery. + * @default null + */ + checksum?: string | null; }; /** * @description Defines source of truth for snapshot recovery: `NoSync` means - restore snapshot without *any* additional synchronization. `Snapshot` means - prefer snapshot data over the current state. `Replica` means - prefer existing data over the snapshot. @@ -2239,6 +2355,11 @@ export interface components { location: components["schemas"]["ShardSnapshotLocation"]; /** @default null */ priority?: components["schemas"]["SnapshotPriority"] | (Record | null); + /** + * @description Optional SHA256 checksum to verify snapshot integrity before recovery. + * @default null + */ + checksum?: string | null; }; ShardSnapshotLocation: string; /** @description Use context and a target to find the most similar points, constrained by the context. */ @@ -2297,6 +2418,15 @@ export interface components { DiscoverRequestBatch: { searches: (components["schemas"]["DiscoverRequest"])[]; }; + VersionInfo: { + title: string; + version: string; + commit?: string | null; + }; + /** @description State of existence of a collection, true = exists, false = does not exist */ + CollectionExistence: { + exists: boolean; + }; }; responses: never; parameters: never; @@ -2409,6 +2539,40 @@ export interface operations { }; }; }; + /** + * Returns information about the running Qdrant instance + * @description Returns information about the running Qdrant instance like version and commit id + */ + root: { + responses: { + /** @description successful operation */ + 200: { + content: { + "application/json": { + /** + * Format: float + * @description Time spent to process this request + */ + time?: number; + status?: string; + result?: components["schemas"]["VersionInfo"]; + }; + }; + }; + /** @description error */ + default: { + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description error */ + "4XX": { + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; /** * Collect telemetry data * @description Collect telemetry data including app info, system info, collections info, cluster info, configs and statistics @@ -3027,6 +3191,46 @@ export interface operations { }; }; }; + /** + * Check the existence of a collection + * @description Returns "true" if the given collection name exists, and "false" otherwise + */ + collection_exists: { + parameters: { + path: { + /** @description Name of the collection */ + collection_name: string; + }; + }; + responses: { + /** @description successful operation */ + 200: { + content: { + "application/json": { + /** + * Format: float + * @description Time spent to process this request + */ + time?: number; + status?: string; + result?: components["schemas"]["CollectionExistence"]; + }; + }; + }; + /** @description error */ + default: { + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description error */ + "4XX": { + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; /** * Delete index for field in collection * @description Delete field index for collection @@ -3250,6 +3454,8 @@ export interface operations { wait?: boolean; /** @description Defines source of truth for snapshot recovery */ priority?: components["schemas"]["SnapshotPriority"]; + /** @description Optional SHA256 checksum to verify snapshot integrity before recovery. */ + checksum?: string; }; path: { /** @description Name of the collection */ @@ -3316,6 +3522,8 @@ export interface operations { query?: { /** @description If true, wait for changes to actually happen. If false - let changes happen in background. Default is true. */ wait?: boolean; + /** @description Optional SHA256 checksum to verify snapshot integrity before recovery. */ + checksum?: string; }; path: { /** @description Name of the collection */ @@ -3747,6 +3955,8 @@ export interface operations { wait?: boolean; /** @description Defines source of truth for snapshot recovery */ priority?: components["schemas"]["SnapshotPriority"]; + /** @description Optional SHA256 checksum to verify snapshot integrity before recovery. */ + checksum?: string; }; path: { /** @description Name of the collection */ @@ -3815,6 +4025,8 @@ export interface operations { query?: { /** @description If true, wait for changes to actually happen. If false - let changes happen in background. Default is true. */ wait?: boolean; + /** @description Optional SHA256 checksum to verify snapshot integrity before recovery. */ + checksum?: string; }; path: { /** @description Name of the collection */ diff --git a/packages/js-client-rest/src/qdrant-client.ts b/packages/js-client-rest/src/qdrant-client.ts index 1af241e..4b05093 100644 --- a/packages/js-client-rest/src/qdrant-client.ts +++ b/packages/js-client-rest/src/qdrant-client.ts @@ -443,6 +443,7 @@ export class QdrantClient { offset, with_payload = true, with_vector = false, + order_by, }: SchemaFor<'ScrollRequest'> & {consistency?: SchemaFor<'ReadConsistency'>} = {}, ) { const response = await this._openApiClient.points.scrollPoints({ @@ -453,6 +454,7 @@ export class QdrantClient { filter, with_payload, with_vector, + order_by, consistency, }); return maybe(response.data.result).orThrow('Scroll points API returned empty'); @@ -845,6 +847,7 @@ export class QdrantClient { * consistent, but may be unavailable if leader is down * - payload: Key-value pairs of payload to assign * - shard_key: Specify in which shards to look for the points, if not specified - look in all shards + * - key: Assigns payload to each point that satisfy this path of property * - points|filter: List of affected points, filter or points selector. * Example: * - `points: [ @@ -869,6 +872,7 @@ export class QdrantClient { points, filter, shard_key, + key, ordering, wait = true, }: {wait?: boolean; ordering?: SchemaFor<'WriteOrdering'>} & SchemaFor<'SetPayload'>, @@ -879,6 +883,7 @@ export class QdrantClient { points, filter, shard_key, + key, wait, ordering, }); @@ -1429,8 +1434,13 @@ export class QdrantClient { * Default: `replica` * @returns True if the snapshot was recovered */ - async recoverSnapshot(collection_name: string, {location, priority}: SchemaFor<'SnapshotRecover'>) { - const response = await this._openApiClient.snapshots.recoverFromSnapshot({collection_name, location, priority}); + async recoverSnapshot(collection_name: string, {location, priority, checksum}: SchemaFor<'SnapshotRecover'>) { + const response = await this._openApiClient.snapshots.recoverFromSnapshot({ + collection_name, + location, + priority, + checksum: checksum === null ? undefined : checksum, + }); return maybe(response.data.result).orThrow('Recover from snapshot API returned empty'); } @@ -1501,12 +1511,13 @@ export class QdrantClient { async recoverShardFromSnapshot( collection_name: string, shard_id: number, - {wait = true, ...shard_snapshot_recover}: {wait?: boolean} & SchemaFor<'ShardSnapshotRecover'>, + {wait = true, checksum, ...shard_snapshot_recover}: {wait?: boolean} & SchemaFor<'ShardSnapshotRecover'>, ) { const response = await this._openApiClient.snapshots.recoverShardFromSnapshot({ collection_name, shard_id, wait, + checksum: checksum === null ? undefined : checksum, ...shard_snapshot_recover, }); return maybe(response.data.result).orThrow('Recover shard from snapshot returned empty'); @@ -1709,4 +1720,22 @@ export class QdrantClient { }); return maybe(response.data.result).orThrow('Discover batch points returned empty'); } + + /** + * Returns information about the running Qdrant instance + * @description Returns information about the running Qdrant instance like version and commit id + */ + async root() { + const response = await this._openApiClient.service.root({}); + return maybe(response.data.result).orThrow('Root returned empty'); + } + + /** + * Check the existence of a collection + * @description Returns "true" if the given collection name exists, and "false" otherwise + */ + async collectionExists(collection_name: string) { + const response = await this._openApiClient.collections.collectionExists({collection_name}); + return maybe(response.data.result).orThrow('Collection exists returned empty'); + } } From 6d0c50b465a3f5eabc3b22fa123e498b17fd4d10 Mon Sep 17 00:00:00 2001 From: Ivan Pleshkov Date: Mon, 4 Mar 2024 09:28:36 +0000 Subject: [PATCH 2/6] grpc api update --- .../js-client-grpc/proto/collections.proto | 67 +++- .../proto/collections_service.proto | 14 +- packages/js-client-grpc/proto/points.proto | 52 +++- .../js-client-grpc/proto/points_service.proto | 50 +-- packages/js-client-grpc/proto/qdrant.proto | 1 + .../proto/snapshots_service.proto | 11 +- .../src/proto/collections_pb.ts | 275 +++++++++++++++- .../src/proto/collections_service_connect.ts | 14 +- .../js-client-grpc/src/proto/points_pb.ts | 293 +++++++++++++++++- .../js-client-grpc/src/proto/qdrant_pb.ts | 6 + .../src/proto/snapshots_service_pb.ts | 8 + 11 files changed, 731 insertions(+), 60 deletions(-) diff --git a/packages/js-client-grpc/proto/collections.proto b/packages/js-client-grpc/proto/collections.proto index 765ffcb..b2a7880 100644 --- a/packages/js-client-grpc/proto/collections.proto +++ b/packages/js-client-grpc/proto/collections.proto @@ -50,6 +50,19 @@ message GetCollectionInfoRequest { string collection_name = 1; // Name of the collection } +message CollectionExistsRequest { + string collection_name = 1; +} + +message CollectionExists { + bool exists = 1; +} + +message CollectionExistsResponse { + CollectionExists result = 1; + double time = 2; // Time spent to process +} + message ListCollectionsRequest { } @@ -90,6 +103,7 @@ enum PayloadSchemaType { Geo = 4; Text = 5; Bool = 6; + Datetime = 7; } enum QuantizationType { @@ -113,7 +127,7 @@ message OptimizerStatus { message HnswConfigDiff { /* Number of edges per node in the index graph. Larger the value - more accurate the search, more space required. - */ + */ optional uint64 m = 1; /* Number of neighbours to consider during the index building. Larger the value - more accurate the search, more time required to build the index. @@ -127,16 +141,19 @@ message HnswConfigDiff { */ optional uint64 full_scan_threshold = 3; /* - Number of parallel threads used for background index building. If 0 - auto selection. - */ + Number of parallel threads used for background index building. + If 0 - automatically select from 8 to 16. + Best to keep between 8 and 16 to prevent likelihood of building broken/inefficient HNSW graphs. + On small CPUs, less threads are used. + */ optional uint64 max_indexing_threads = 4; /* Store HNSW index on disk. If set to false, the index will be stored in RAM. - */ + */ optional bool on_disk = 5; /* - Number of additional payload-aware links per node in the index graph. If not set - regular M parameter will be used. - */ + Number of additional payload-aware links per node in the index graph. If not set - regular M parameter will be used. + */ optional uint64 payload_m = 6; } @@ -160,11 +177,11 @@ message WalConfigDiff { message OptimizersConfigDiff { /* The minimal fraction of deleted vectors in a segment, required to perform segment optimization - */ + */ optional double deleted_threshold = 1; /* The minimal number of vectors in a segment, required to perform segment optimization - */ + */ optional uint64 vacuum_min_vector_number = 2; /* Target amount of segments the optimizer will try to keep. @@ -181,7 +198,7 @@ message OptimizersConfigDiff { Do not create segments larger this size (in kilobytes). Large segments might require disproportionately long indexation times, therefore it makes sense to limit the size of segments. - + If indexing speed is more important - make this parameter lower. If search speed is more important - make this parameter higher. Note: 1Kb = 1 vector of size 256 @@ -201,11 +218,11 @@ message OptimizersConfigDiff { optional uint64 memmap_threshold = 5; /* Maximum size (in kilobytes) of vectors allowed for plain index, exceeding this threshold will enable vector indexing - + Default value is 20,000, based on . - + To disable vector indexing, set to `0`. - + Note: 1kB = 1 vector of size 256. */ optional uint64 indexing_threshold = 6; @@ -214,7 +231,10 @@ message OptimizersConfigDiff { */ optional uint64 flush_interval_sec = 7; /* - Max number of threads, which can be used for optimization. If 0 - `NUM_CPU - 1` will be used + Max number of threads (jobs) for running optimizations per shard. + Note: each optimization job will also use `max_indexing_threads` threads by itself for index building. + If null - have no limit and choose dynamically to saturate CPU. + If 0 - no optimization threads, optimizations will be disabled. */ optional uint64 max_optimization_threads = 8; } @@ -343,9 +363,15 @@ message TextIndexParams { optional uint64 max_token_len = 4; // Maximal token length } +message IntegerIndexParams { + bool lookup = 1; // If true - support direct lookups. + bool range = 2; // If true - support ranges filters. +} + message PayloadIndexParams { oneof index_params { TextIndexParams text_index_params = 1; // Parameters for text index + IntegerIndexParams integer_index_params = 2; // Parameters for integer index } } @@ -423,6 +449,8 @@ enum ReplicaState { Initializing = 3; // Collection is being created Listener = 4; // A shard which receives data, but is not used for search; Useful for backup shards PartialSnapshot = 5; // Snapshot shard transfer is in progress; Updates should not be sent to (and are ignored by) the shard + Recovery = 6; // Shard is undergoing recovered by an external node; Normally rejects updates, accepts updates if force is true + // TODO(1.9): deprecate PartialSnapshot state } message ShardKey { @@ -468,9 +496,17 @@ message MoveShard { optional ShardTransferMethod method = 4; } +message RestartTransfer { + uint32 shard_id = 1; // Local shard id + uint64 from_peer_id = 2; + uint64 to_peer_id = 3; + ShardTransferMethod method = 4; +} + enum ShardTransferMethod { - StreamRecords = 0; - Snapshot = 1; + StreamRecords = 0; // Stream shard records in batches + Snapshot = 1; // Snapshot the shard and recover it on the target peer + WalDelta = 2; // Resolve WAL delta between peers and transfer the difference } message Replica { @@ -498,6 +534,7 @@ message UpdateCollectionClusterSetupRequest { Replica drop_replica = 5; CreateShardKey create_shard_key = 7; DeleteShardKey delete_shard_key = 8; + RestartTransfer restart_transfer = 9; } optional uint64 timeout = 6; // Wait timeout for operation commit in seconds, if not specified - default value will be supplied } diff --git a/packages/js-client-grpc/proto/collections_service.proto b/packages/js-client-grpc/proto/collections_service.proto index 723124e..52caa8d 100644 --- a/packages/js-client-grpc/proto/collections_service.proto +++ b/packages/js-client-grpc/proto/collections_service.proto @@ -8,23 +8,23 @@ option csharp_namespace = "Qdrant.Client.Grpc"; service Collections { /* Get detailed information about specified existing collection - */ + */ rpc Get (GetCollectionInfoRequest) returns (GetCollectionInfoResponse) {} /* Get list name of all existing collections - */ + */ rpc List (ListCollectionsRequest) returns (ListCollectionsResponse) {} /* Create new collection with given parameters - */ + */ rpc Create (CreateCollection) returns (CollectionOperationResponse) {} /* Update parameters of the existing collection - */ + */ rpc Update (UpdateCollection) returns (CollectionOperationResponse) {} /* Drop collection and all associated data - */ + */ rpc Delete (DeleteCollection) returns (CollectionOperationResponse) {} /* Update Aliases of the existing collection @@ -43,6 +43,10 @@ service Collections { */ rpc CollectionClusterInfo (CollectionClusterInfoRequest) returns (CollectionClusterInfoResponse) {} /* + Check the existence of a collection + */ + rpc CollectionExists (CollectionExistsRequest) returns (CollectionExistsResponse) {} + /* Update cluster setup for a collection */ rpc UpdateCollectionClusterSetup (UpdateCollectionClusterSetupRequest) returns (UpdateCollectionClusterSetupResponse) {} diff --git a/packages/js-client-grpc/proto/points.proto b/packages/js-client-grpc/proto/points.proto index f95a4d3..3e19e0a 100644 --- a/packages/js-client-grpc/proto/points.proto +++ b/packages/js-client-grpc/proto/points.proto @@ -3,8 +3,9 @@ syntax = "proto3"; package qdrant; option csharp_namespace = "Qdrant.Client.Grpc"; -import "json_with_int.proto"; import "collections.proto"; +import "google/protobuf/timestamp.proto"; +import "json_with_int.proto"; enum WriteOrderingType { @@ -118,6 +119,7 @@ message SetPayloadPoints { optional PointsSelector points_selector = 5; // Affected points optional WriteOrdering ordering = 6; // Write ordering guarantees optional ShardKeySelector shard_key_selector = 7; // Option for custom sharding to specify used shard keys + optional string key = 8; // Option for indicate property of payload } message DeletePayloadPoints { @@ -145,6 +147,7 @@ enum FieldType { FieldTypeGeo = 3; FieldTypeText = 4; FieldTypeBool = 5; + FieldTypeDatetime = 6; } message CreateFieldIndexCollection { @@ -204,12 +207,12 @@ message WithVectorsSelector { message QuantizationSearchParams { /* If set to true, search will ignore quantized vector data - */ + */ optional bool ignore = 1; /* If true, use original vectors to re-score top-k results. If ignored, qdrant decides automatically does rescore enabled or not. - */ + */ optional bool rescore = 2; /* @@ -220,7 +223,7 @@ message QuantizationSearchParams { For example, if `oversampling` is 2.4 and `limit` is 100, then 240 vectors will be pre-selected using quantized index, and then top-100 will be returned after re-scoring. - */ + */ optional double oversampling = 3; } @@ -228,7 +231,7 @@ message SearchParams { /* Params relevant to HNSW index. Size of the beam in a beam-search. Larger the value - more accurate the result, more time required for search. - */ + */ optional uint64 hnsw_ef = 1; /* @@ -244,7 +247,7 @@ message SearchParams { If enabled, the engine will only perform search among indexed or small segments. Using this option prevents slow searches in case of delayed index, but does not guarantee that all uploaded vectors will be included in search results - */ + */ optional bool indexed_only = 4; } @@ -299,6 +302,26 @@ message SearchPointGroups { optional SparseIndices sparse_indices = 16; } +enum Direction { + Asc = 0; + Desc = 1; +} + +message StartFrom { + oneof value { + double float = 1; + int64 integer = 2; + google.protobuf.Timestamp timestamp = 3; + string datetime = 4; + } +} + +message OrderBy { + string key = 1; // Payload key to order by + optional Direction direction = 2; // Ascending or descending order + optional StartFrom start_from = 3; // Start from this value +} + message ScrollPoints { string collection_name = 1; Filter filter = 2; // Filter conditions - return only those points that satisfy the specified conditions @@ -309,6 +332,7 @@ message ScrollPoints { optional WithVectorsSelector with_vectors = 7; // Options for specifying which vectors to include into response optional ReadConsistency read_consistency = 8; // Options for specifying read consistency guarantees optional ShardKeySelector shard_key_selector = 9; // Specify in which shards to look for the points, if not specified - look in all shards + optional OrderBy order_by = 10; // Order the records by a payload field } // How to use positive and negative vectors to find the results, default is `AverageVector`: @@ -442,6 +466,7 @@ message PointsUpdateOperation { map payload = 1; optional PointsSelector points_selector = 2; // Affected points optional ShardKeySelector shard_key_selector = 3; // Option for custom sharding to specify used shard keys + optional string key = 4; // Option for indicate property of payload } message DeletePayload { repeated string keys = 1; @@ -505,6 +530,7 @@ enum UpdateStatus { UnknownUpdateStatus = 0; Acknowledged = 1; // Update is received, but not processed yet Completed = 2; // Update is applied and ready for search + ClockRejected = 3; // Internal: update is rejected due to an outdated clock } message ScoredPoint { @@ -623,6 +649,12 @@ message Filter { repeated Condition should = 1; // At least one of those conditions should match repeated Condition must = 2; // All conditions must match repeated Condition must_not = 3; // All conditions must NOT match + optional MinShould min_should = 4; // At least minimum amount of given conditions should match +} + +message MinShould { + repeated Condition conditions = 1; + uint64 min_count = 2; } message Condition { @@ -661,6 +693,7 @@ message FieldCondition { GeoRadius geo_radius = 5; // Check if geo point is within a given radius ValuesCount values_count = 6; // Check number of values for a specific field GeoPolygon geo_polygon = 7; // Check if geo point is within a given polygon + DatetimeRange datetime_range = 8; // Check if datetime is within a given range } message Match { @@ -691,6 +724,13 @@ message Range { optional double lte = 4; } +message DatetimeRange { + optional google.protobuf.Timestamp lt = 1; + optional google.protobuf.Timestamp gt = 2; + optional google.protobuf.Timestamp gte = 3; + optional google.protobuf.Timestamp lte = 4; +} + message GeoBoundingBox { GeoPoint top_left = 1; // north-west corner GeoPoint bottom_right = 2; // south-east corner diff --git a/packages/js-client-grpc/proto/points_service.proto b/packages/js-client-grpc/proto/points_service.proto index ddfdc62..9338d07 100644 --- a/packages/js-client-grpc/proto/points_service.proto +++ b/packages/js-client-grpc/proto/points_service.proto @@ -8,59 +8,59 @@ option csharp_namespace = "Qdrant.Client.Grpc"; service Points { /* Perform insert + updates on points. If a point with a given ID already exists - it will be overwritten. - */ + */ rpc Upsert (UpsertPoints) returns (PointsOperationResponse) {} /* Delete points - */ + */ rpc Delete (DeletePoints) returns (PointsOperationResponse) {} /* Retrieve points - */ + */ rpc Get (GetPoints) returns (GetResponse) {} /* Update named vectors for point - */ + */ rpc UpdateVectors (UpdatePointVectors) returns (PointsOperationResponse) {} /* Delete named vectors for points - */ + */ rpc DeleteVectors (DeletePointVectors) returns (PointsOperationResponse) {} /* Set payload for points - */ + */ rpc SetPayload (SetPayloadPoints) returns (PointsOperationResponse) {} /* Overwrite payload for points - */ + */ rpc OverwritePayload (SetPayloadPoints) returns (PointsOperationResponse) {} /* Delete specified key payload for points - */ + */ rpc DeletePayload (DeletePayloadPoints) returns (PointsOperationResponse) {} /* Remove all payload for specified points - */ + */ rpc ClearPayload (ClearPayloadPoints) returns (PointsOperationResponse) {} /* Create index for field in collection - */ + */ rpc CreateFieldIndex (CreateFieldIndexCollection) returns (PointsOperationResponse) {} /* Delete field index for collection - */ + */ rpc DeleteFieldIndex (DeleteFieldIndexCollection) returns (PointsOperationResponse) {} /* Retrieve closest points based on vector similarity and given filtering conditions - */ + */ rpc Search (SearchPoints) returns (SearchResponse) {} /* - Retrieve closest points based on vector similarity and given filtering conditions - */ + Retrieve closest points based on vector similarity and given filtering conditions + */ rpc SearchBatch (SearchBatchPoints) returns (SearchBatchResponse) {} /* Retrieve closest points based on vector similarity and given filtering conditions, grouped by a given field - */ + */ rpc SearchGroups (SearchPointGroups) returns (SearchGroupsResponse) {} /* Iterate over all or filtered points @@ -68,19 +68,19 @@ service Points { rpc Scroll (ScrollPoints) returns (ScrollResponse) {} /* Look for the points which are closer to stored positive examples and at the same time further to negative examples. - */ + */ rpc Recommend (RecommendPoints) returns (RecommendResponse) {} /* Look for the points which are closer to stored positive examples and at the same time further to negative examples. - */ + */ rpc RecommendBatch (RecommendBatchPoints) returns (RecommendBatchResponse) {} /* Look for the points which are closer to stored positive examples and at the same time further to negative examples, grouped by a given field - */ + */ rpc RecommendGroups (RecommendPointGroups) returns (RecommendGroupsResponse) {} /* Use context and a target to find the most similar points to the target, constrained by the context. - + When using only the context (without a target), a special search - called context search - is performed where pairs of points are used to generate a loss that guides the search towards the zone where most positive examples overlap. This means that the score minimizes the scenario of @@ -88,25 +88,25 @@ service Points { Since the score of a context relates to loss, the maximum score a point can get is 0.0, and it becomes normal that many points can have a score of 0.0. - + When using target (with or without context), the score behaves a little different: The integer part of the score represents the rank with respect to the context, while the decimal part of the score relates to the distance to the target. The context part of the score for each pair is calculated +1 if the point is closer to a positive than to a negative part of a pair, and -1 otherwise. - */ + */ rpc Discover (DiscoverPoints) returns (DiscoverResponse) {} /* Batch request points based on { positive, negative } pairs of examples, and/or a target - */ + */ rpc DiscoverBatch (DiscoverBatchPoints) returns (DiscoverBatchResponse) {} /* - Count points in collection with given filtering conditions - */ + Count points in collection with given filtering conditions + */ rpc Count (CountPoints) returns (CountResponse) {} /* - Perform multiple update operations in one request + Perform multiple update operations in one request */ rpc UpdateBatch (UpdateBatchPoints) returns (UpdateBatchResponse) {} } diff --git a/packages/js-client-grpc/proto/qdrant.proto b/packages/js-client-grpc/proto/qdrant.proto index 4f58399..723bb65 100644 --- a/packages/js-client-grpc/proto/qdrant.proto +++ b/packages/js-client-grpc/proto/qdrant.proto @@ -16,4 +16,5 @@ message HealthCheckRequest {} message HealthCheckReply { string title = 1; string version = 2; + optional string commit = 3; } diff --git a/packages/js-client-grpc/proto/snapshots_service.proto b/packages/js-client-grpc/proto/snapshots_service.proto index 5127b28..63c9e51 100644 --- a/packages/js-client-grpc/proto/snapshots_service.proto +++ b/packages/js-client-grpc/proto/snapshots_service.proto @@ -7,16 +7,16 @@ import "google/protobuf/timestamp.proto"; service Snapshots { /* - Create collection snapshot + Create collection snapshot */ rpc Create (CreateSnapshotRequest) returns (CreateSnapshotResponse) {} /* List collection snapshots - */ + */ rpc List (ListSnapshotsRequest) returns (ListSnapshotsResponse) {} /* Delete collection snapshot - */ + */ rpc Delete (DeleteSnapshotRequest) returns (DeleteSnapshotResponse) {} /* Create full storage snapshot @@ -24,11 +24,11 @@ service Snapshots { rpc CreateFull (CreateFullSnapshotRequest) returns (CreateSnapshotResponse) {} /* List full storage snapshots - */ + */ rpc ListFull (ListFullSnapshotsRequest) returns (ListSnapshotsResponse) {} /* Delete full storage snapshot - */ + */ rpc DeleteFull (DeleteFullSnapshotRequest) returns (DeleteSnapshotResponse) {} } @@ -57,6 +57,7 @@ message SnapshotDescription { string name = 1; // Name of the snapshot google.protobuf.Timestamp creation_time = 2; // Creation time of the snapshot int64 size = 3; // Size of the snapshot in bytes + optional string checksum = 4; // SHA256 digest of the snapshot file } message CreateSnapshotResponse { diff --git a/packages/js-client-grpc/src/proto/collections_pb.ts b/packages/js-client-grpc/src/proto/collections_pb.ts index 9a9f556..0cc9e37 100644 --- a/packages/js-client-grpc/src/proto/collections_pb.ts +++ b/packages/js-client-grpc/src/proto/collections_pb.ts @@ -120,6 +120,11 @@ export enum PayloadSchemaType { * @generated from enum value: Bool = 6; */ Bool = 6, + + /** + * @generated from enum value: Datetime = 7; + */ + Datetime = 7, } // Retrieve enum metadata with: proto3.getEnumType(PayloadSchemaType) proto3.util.setEnumType(PayloadSchemaType, "qdrant.PayloadSchemaType", [ @@ -130,6 +135,7 @@ proto3.util.setEnumType(PayloadSchemaType, "qdrant.PayloadSchemaType", [ { no: 4, name: "Geo" }, { no: 5, name: "Text" }, { no: 6, name: "Bool" }, + { no: 7, name: "Datetime" }, ]); /** @@ -297,6 +303,13 @@ export enum ReplicaState { * @generated from enum value: PartialSnapshot = 5; */ PartialSnapshot = 5, + + /** + * Shard is undergoing recovered by an external node; Normally rejects updates, accepts updates if force is true + * + * @generated from enum value: Recovery = 6; + */ + Recovery = 6, } // Retrieve enum metadata with: proto3.getEnumType(ReplicaState) proto3.util.setEnumType(ReplicaState, "qdrant.ReplicaState", [ @@ -306,6 +319,7 @@ proto3.util.setEnumType(ReplicaState, "qdrant.ReplicaState", [ { no: 3, name: "Initializing" }, { no: 4, name: "Listener" }, { no: 5, name: "PartialSnapshot" }, + { no: 6, name: "Recovery" }, ]); /** @@ -313,19 +327,31 @@ proto3.util.setEnumType(ReplicaState, "qdrant.ReplicaState", [ */ export enum ShardTransferMethod { /** + * Stream shard records in batches + * * @generated from enum value: StreamRecords = 0; */ StreamRecords = 0, /** + * Snapshot the shard and recover it on the target peer + * * @generated from enum value: Snapshot = 1; */ Snapshot = 1, + + /** + * Resolve WAL delta between peers and transfer the difference + * + * @generated from enum value: WalDelta = 2; + */ + WalDelta = 2, } // Retrieve enum metadata with: proto3.getEnumType(ShardTransferMethod) proto3.util.setEnumType(ShardTransferMethod, "qdrant.ShardTransferMethod", [ { no: 0, name: "StreamRecords" }, { no: 1, name: "Snapshot" }, + { no: 2, name: "WalDelta" }, ]); /** @@ -743,6 +769,125 @@ export class GetCollectionInfoRequest extends Message } } +/** + * @generated from message qdrant.CollectionExistsRequest + */ +export class CollectionExistsRequest extends Message { + /** + * @generated from field: string collection_name = 1; + */ + collectionName = ""; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "qdrant.CollectionExistsRequest"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "collection_name", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): CollectionExistsRequest { + return new CollectionExistsRequest().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): CollectionExistsRequest { + return new CollectionExistsRequest().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): CollectionExistsRequest { + return new CollectionExistsRequest().fromJsonString(jsonString, options); + } + + static equals(a: CollectionExistsRequest | PlainMessage | undefined, b: CollectionExistsRequest | PlainMessage | undefined): boolean { + return proto3.util.equals(CollectionExistsRequest, a, b); + } +} + +/** + * @generated from message qdrant.CollectionExists + */ +export class CollectionExists extends Message { + /** + * @generated from field: bool exists = 1; + */ + exists = false; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "qdrant.CollectionExists"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "exists", kind: "scalar", T: 8 /* ScalarType.BOOL */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): CollectionExists { + return new CollectionExists().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): CollectionExists { + return new CollectionExists().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): CollectionExists { + return new CollectionExists().fromJsonString(jsonString, options); + } + + static equals(a: CollectionExists | PlainMessage | undefined, b: CollectionExists | PlainMessage | undefined): boolean { + return proto3.util.equals(CollectionExists, a, b); + } +} + +/** + * @generated from message qdrant.CollectionExistsResponse + */ +export class CollectionExistsResponse extends Message { + /** + * @generated from field: qdrant.CollectionExists result = 1; + */ + result?: CollectionExists; + + /** + * Time spent to process + * + * @generated from field: double time = 2; + */ + time = 0; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "qdrant.CollectionExistsResponse"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "result", kind: "message", T: CollectionExists }, + { no: 2, name: "time", kind: "scalar", T: 1 /* ScalarType.DOUBLE */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): CollectionExistsResponse { + return new CollectionExistsResponse().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): CollectionExistsResponse { + return new CollectionExistsResponse().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): CollectionExistsResponse { + return new CollectionExistsResponse().fromJsonString(jsonString, options); + } + + static equals(a: CollectionExistsResponse | PlainMessage | undefined, b: CollectionExistsResponse | PlainMessage | undefined): boolean { + return proto3.util.equals(CollectionExistsResponse, a, b); + } +} + /** * @generated from message qdrant.ListCollectionsRequest */ @@ -979,7 +1124,10 @@ export class HnswConfigDiff extends Message { /** * - * Number of parallel threads used for background index building. If 0 - auto selection. + * Number of parallel threads used for background index building. + * If 0 - automatically select from 8 to 16. + * Best to keep between 8 and 16 to prevent likelihood of building broken/inefficient HNSW graphs. + * On small CPUs, less threads are used. * * @generated from field: optional uint64 max_indexing_threads = 4; */ @@ -1220,7 +1368,10 @@ export class OptimizersConfigDiff extends Message { /** * - * Max number of threads, which can be used for optimization. If 0 - `NUM_CPU - 1` will be used + * Max number of threads (jobs) for running optimizations per shard. + * Note: each optimization job will also use `max_indexing_threads` threads by itself for index building. + * If null - have no limit and choose dynamically to saturate CPU. + * If 0 - no optimization threads, optimizations will be disabled. * * @generated from field: optional uint64 max_optimization_threads = 8; */ @@ -2178,6 +2329,53 @@ export class TextIndexParams extends Message { } } +/** + * @generated from message qdrant.IntegerIndexParams + */ +export class IntegerIndexParams extends Message { + /** + * If true - support direct lookups. + * + * @generated from field: bool lookup = 1; + */ + lookup = false; + + /** + * If true - support ranges filters. + * + * @generated from field: bool range = 2; + */ + range = false; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "qdrant.IntegerIndexParams"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "lookup", kind: "scalar", T: 8 /* ScalarType.BOOL */ }, + { no: 2, name: "range", kind: "scalar", T: 8 /* ScalarType.BOOL */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): IntegerIndexParams { + return new IntegerIndexParams().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): IntegerIndexParams { + return new IntegerIndexParams().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): IntegerIndexParams { + return new IntegerIndexParams().fromJsonString(jsonString, options); + } + + static equals(a: IntegerIndexParams | PlainMessage | undefined, b: IntegerIndexParams | PlainMessage | undefined): boolean { + return proto3.util.equals(IntegerIndexParams, a, b); + } +} + /** * @generated from message qdrant.PayloadIndexParams */ @@ -2193,6 +2391,14 @@ export class PayloadIndexParams extends Message { */ value: TextIndexParams; case: "textIndexParams"; + } | { + /** + * Parameters for integer index + * + * @generated from field: qdrant.IntegerIndexParams integer_index_params = 2; + */ + value: IntegerIndexParams; + case: "integerIndexParams"; } | { case: undefined; value?: undefined } = { case: undefined }; constructor(data?: PartialMessage) { @@ -2204,6 +2410,7 @@ export class PayloadIndexParams extends Message { static readonly typeName = "qdrant.PayloadIndexParams"; static readonly fields: FieldList = proto3.util.newFieldList(() => [ { no: 1, name: "text_index_params", kind: "message", T: TextIndexParams, oneof: "index_params" }, + { no: 2, name: "integer_index_params", kind: "message", T: IntegerIndexParams, oneof: "index_params" }, ]); static fromBinary(bytes: Uint8Array, options?: Partial): PayloadIndexParams { @@ -3178,6 +3385,63 @@ export class MoveShard extends Message { } } +/** + * @generated from message qdrant.RestartTransfer + */ +export class RestartTransfer extends Message { + /** + * Local shard id + * + * @generated from field: uint32 shard_id = 1; + */ + shardId = 0; + + /** + * @generated from field: uint64 from_peer_id = 2; + */ + fromPeerId = protoInt64.zero; + + /** + * @generated from field: uint64 to_peer_id = 3; + */ + toPeerId = protoInt64.zero; + + /** + * @generated from field: qdrant.ShardTransferMethod method = 4; + */ + method = ShardTransferMethod.StreamRecords; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "qdrant.RestartTransfer"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "shard_id", kind: "scalar", T: 13 /* ScalarType.UINT32 */ }, + { no: 2, name: "from_peer_id", kind: "scalar", T: 4 /* ScalarType.UINT64 */ }, + { no: 3, name: "to_peer_id", kind: "scalar", T: 4 /* ScalarType.UINT64 */ }, + { no: 4, name: "method", kind: "enum", T: proto3.getEnumType(ShardTransferMethod) }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): RestartTransfer { + return new RestartTransfer().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): RestartTransfer { + return new RestartTransfer().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): RestartTransfer { + return new RestartTransfer().fromJsonString(jsonString, options); + } + + static equals(a: RestartTransfer | PlainMessage | undefined, b: RestartTransfer | PlainMessage | undefined): boolean { + return proto3.util.equals(RestartTransfer, a, b); + } +} + /** * @generated from message qdrant.Replica */ @@ -3373,6 +3637,12 @@ export class UpdateCollectionClusterSetupRequest extends Message { */ shardKeySelector?: ShardKeySelector; + /** + * Option for indicate property of payload + * + * @generated from field: optional string key = 8; + */ + key?: string; + constructor(data?: PartialMessage) { super(); proto3.util.initPartial(data, this); @@ -921,6 +962,7 @@ export class SetPayloadPoints extends Message { { no: 5, name: "points_selector", kind: "message", T: PointsSelector, opt: true }, { no: 6, name: "ordering", kind: "message", T: WriteOrdering, opt: true }, { no: 7, name: "shard_key_selector", kind: "message", T: ShardKeySelector, opt: true }, + { no: 8, name: "key", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, ]); static fromBinary(bytes: Uint8Array, options?: Partial): SetPayloadPoints { @@ -2097,6 +2139,125 @@ export class SearchPointGroups extends Message { } } +/** + * @generated from message qdrant.StartFrom + */ +export class StartFrom extends Message { + /** + * @generated from oneof qdrant.StartFrom.value + */ + value: { + /** + * @generated from field: double float = 1; + */ + value: number; + case: "float"; + } | { + /** + * @generated from field: int64 integer = 2; + */ + value: bigint; + case: "integer"; + } | { + /** + * @generated from field: google.protobuf.Timestamp timestamp = 3; + */ + value: Timestamp; + case: "timestamp"; + } | { + /** + * @generated from field: string datetime = 4; + */ + value: string; + case: "datetime"; + } | { case: undefined; value?: undefined } = { case: undefined }; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "qdrant.StartFrom"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "float", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, oneof: "value" }, + { no: 2, name: "integer", kind: "scalar", T: 3 /* ScalarType.INT64 */, oneof: "value" }, + { no: 3, name: "timestamp", kind: "message", T: Timestamp, oneof: "value" }, + { no: 4, name: "datetime", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "value" }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): StartFrom { + return new StartFrom().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): StartFrom { + return new StartFrom().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): StartFrom { + return new StartFrom().fromJsonString(jsonString, options); + } + + static equals(a: StartFrom | PlainMessage | undefined, b: StartFrom | PlainMessage | undefined): boolean { + return proto3.util.equals(StartFrom, a, b); + } +} + +/** + * @generated from message qdrant.OrderBy + */ +export class OrderBy extends Message { + /** + * Payload key to order by + * + * @generated from field: string key = 1; + */ + key = ""; + + /** + * Ascending or descending order + * + * @generated from field: optional qdrant.Direction direction = 2; + */ + direction?: Direction; + + /** + * Start from this value + * + * @generated from field: optional qdrant.StartFrom start_from = 3; + */ + startFrom?: StartFrom; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "qdrant.OrderBy"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "key", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "direction", kind: "enum", T: proto3.getEnumType(Direction), opt: true }, + { no: 3, name: "start_from", kind: "message", T: StartFrom, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): OrderBy { + return new OrderBy().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): OrderBy { + return new OrderBy().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): OrderBy { + return new OrderBy().fromJsonString(jsonString, options); + } + + static equals(a: OrderBy | PlainMessage | undefined, b: OrderBy | PlainMessage | undefined): boolean { + return proto3.util.equals(OrderBy, a, b); + } +} + /** * @generated from message qdrant.ScrollPoints */ @@ -2155,6 +2316,13 @@ export class ScrollPoints extends Message { */ shardKeySelector?: ShardKeySelector; + /** + * Order the records by a payload field + * + * @generated from field: optional qdrant.OrderBy order_by = 10; + */ + orderBy?: OrderBy; + constructor(data?: PartialMessage) { super(); proto3.util.initPartial(data, this); @@ -2171,6 +2339,7 @@ export class ScrollPoints extends Message { { no: 7, name: "with_vectors", kind: "message", T: WithVectorsSelector, opt: true }, { no: 8, name: "read_consistency", kind: "message", T: ReadConsistency, opt: true }, { no: 9, name: "shard_key_selector", kind: "message", T: ShardKeySelector, opt: true }, + { no: 10, name: "order_by", kind: "message", T: OrderBy, opt: true }, ]); static fromBinary(bytes: Uint8Array, options?: Partial): ScrollPoints { @@ -3257,6 +3426,13 @@ export class PointsUpdateOperation_SetPayload extends Message) { super(); proto3.util.initPartial(data, this); @@ -3268,6 +3444,7 @@ export class PointsUpdateOperation_SetPayload extends Message): PointsUpdateOperation_SetPayload { @@ -4629,6 +4806,13 @@ export class Filter extends Message { */ mustNot: Condition[] = []; + /** + * At least minimum amount of given conditions should match + * + * @generated from field: optional qdrant.MinShould min_should = 4; + */ + minShould?: MinShould; + constructor(data?: PartialMessage) { super(); proto3.util.initPartial(data, this); @@ -4640,6 +4824,7 @@ export class Filter extends Message { { no: 1, name: "should", kind: "message", T: Condition, repeated: true }, { no: 2, name: "must", kind: "message", T: Condition, repeated: true }, { no: 3, name: "must_not", kind: "message", T: Condition, repeated: true }, + { no: 4, name: "min_should", kind: "message", T: MinShould, opt: true }, ]); static fromBinary(bytes: Uint8Array, options?: Partial): Filter { @@ -4659,6 +4844,49 @@ export class Filter extends Message { } } +/** + * @generated from message qdrant.MinShould + */ +export class MinShould extends Message { + /** + * @generated from field: repeated qdrant.Condition conditions = 1; + */ + conditions: Condition[] = []; + + /** + * @generated from field: uint64 min_count = 2; + */ + minCount = protoInt64.zero; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "qdrant.MinShould"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "conditions", kind: "message", T: Condition, repeated: true }, + { no: 2, name: "min_count", kind: "scalar", T: 4 /* ScalarType.UINT64 */ }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): MinShould { + return new MinShould().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): MinShould { + return new MinShould().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): MinShould { + return new MinShould().fromJsonString(jsonString, options); + } + + static equals(a: MinShould | PlainMessage | undefined, b: MinShould | PlainMessage | undefined): boolean { + return proto3.util.equals(MinShould, a, b); + } +} + /** * @generated from message qdrant.Condition */ @@ -4946,6 +5174,13 @@ export class FieldCondition extends Message { */ geoPolygon?: GeoPolygon; + /** + * Check if datetime is within a given range + * + * @generated from field: qdrant.DatetimeRange datetime_range = 8; + */ + datetimeRange?: DatetimeRange; + constructor(data?: PartialMessage) { super(); proto3.util.initPartial(data, this); @@ -4961,6 +5196,7 @@ export class FieldCondition extends Message { { no: 5, name: "geo_radius", kind: "message", T: GeoRadius }, { no: 6, name: "values_count", kind: "message", T: ValuesCount }, { no: 7, name: "geo_polygon", kind: "message", T: GeoPolygon }, + { no: 8, name: "datetime_range", kind: "message", T: DatetimeRange }, ]); static fromBinary(bytes: Uint8Array, options?: Partial): FieldCondition { @@ -5217,6 +5453,61 @@ export class Range extends Message { } } +/** + * @generated from message qdrant.DatetimeRange + */ +export class DatetimeRange extends Message { + /** + * @generated from field: optional google.protobuf.Timestamp lt = 1; + */ + lt?: Timestamp; + + /** + * @generated from field: optional google.protobuf.Timestamp gt = 2; + */ + gt?: Timestamp; + + /** + * @generated from field: optional google.protobuf.Timestamp gte = 3; + */ + gte?: Timestamp; + + /** + * @generated from field: optional google.protobuf.Timestamp lte = 4; + */ + lte?: Timestamp; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "qdrant.DatetimeRange"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "lt", kind: "message", T: Timestamp, opt: true }, + { no: 2, name: "gt", kind: "message", T: Timestamp, opt: true }, + { no: 3, name: "gte", kind: "message", T: Timestamp, opt: true }, + { no: 4, name: "lte", kind: "message", T: Timestamp, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): DatetimeRange { + return new DatetimeRange().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): DatetimeRange { + return new DatetimeRange().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): DatetimeRange { + return new DatetimeRange().fromJsonString(jsonString, options); + } + + static equals(a: DatetimeRange | PlainMessage | undefined, b: DatetimeRange | PlainMessage | undefined): boolean { + return proto3.util.equals(DatetimeRange, a, b); + } +} + /** * @generated from message qdrant.GeoBoundingBox */ diff --git a/packages/js-client-grpc/src/proto/qdrant_pb.ts b/packages/js-client-grpc/src/proto/qdrant_pb.ts index 1204191..7cc123a 100644 --- a/packages/js-client-grpc/src/proto/qdrant_pb.ts +++ b/packages/js-client-grpc/src/proto/qdrant_pb.ts @@ -51,6 +51,11 @@ export class HealthCheckReply extends Message { */ version = ""; + /** + * @generated from field: optional string commit = 3; + */ + commit?: string; + constructor(data?: PartialMessage) { super(); proto3.util.initPartial(data, this); @@ -61,6 +66,7 @@ export class HealthCheckReply extends Message { static readonly fields: FieldList = proto3.util.newFieldList(() => [ { no: 1, name: "title", kind: "scalar", T: 9 /* ScalarType.STRING */ }, { no: 2, name: "version", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 3, name: "commit", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, ]); static fromBinary(bytes: Uint8Array, options?: Partial): HealthCheckReply { diff --git a/packages/js-client-grpc/src/proto/snapshots_service_pb.ts b/packages/js-client-grpc/src/proto/snapshots_service_pb.ts index 539e8b8..e257630 100644 --- a/packages/js-client-grpc/src/proto/snapshots_service_pb.ts +++ b/packages/js-client-grpc/src/proto/snapshots_service_pb.ts @@ -257,6 +257,13 @@ export class SnapshotDescription extends Message { */ size = protoInt64.zero; + /** + * SHA256 digest of the snapshot file + * + * @generated from field: optional string checksum = 4; + */ + checksum?: string; + constructor(data?: PartialMessage) { super(); proto3.util.initPartial(data, this); @@ -268,6 +275,7 @@ export class SnapshotDescription extends Message { { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */ }, { no: 2, name: "creation_time", kind: "message", T: Timestamp }, { no: 3, name: "size", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, + { no: 4, name: "checksum", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, ]); static fromBinary(bytes: Uint8Array, options?: Partial): SnapshotDescription { From 8083f3fcd9dc82d4816db45efecebea36c0890c1 Mon Sep 17 00:00:00 2001 From: Ivan Pleshkov Date: Mon, 4 Mar 2024 09:51:37 +0000 Subject: [PATCH 3/6] version up --- examples/node-js-basic/package.json | 2 +- packages/js-client-grpc/CHANGELOG.md | 9 ++++++++- packages/js-client-grpc/package.json | 2 +- packages/js-client-rest/CHANGELOG.md | 8 ++++++++ packages/js-client-rest/package.json | 2 +- packages/qdrant-js/CHANGELOG.md | 13 +++++++++++++ packages/qdrant-js/package.json | 6 +++--- pnpm-lock.yaml | 4 ++-- 8 files changed, 37 insertions(+), 9 deletions(-) diff --git a/examples/node-js-basic/package.json b/examples/node-js-basic/package.json index cb48cb8..f75a3aa 100644 --- a/examples/node-js-basic/package.json +++ b/examples/node-js-basic/package.json @@ -15,6 +15,6 @@ "author": "Qdrant Team", "license": "Apache-2.0", "dependencies": { - "@qdrant/qdrant-js": "^1.7.0" + "@qdrant/qdrant-js": "^1.8.0" } } diff --git a/packages/js-client-grpc/CHANGELOG.md b/packages/js-client-grpc/CHANGELOG.md index 42e2266..9a4425e 100644 --- a/packages/js-client-grpc/CHANGELOG.md +++ b/packages/js-client-grpc/CHANGELOG.md @@ -1,11 +1,18 @@ # @qdrant/js-client-grpc +## 1.8.0 + +### Minor Changes + +- Qdrant v1.8.0 API +- [#62](https://github.com/qdrant/qdrant-js/pull/62) Thanks [@Rendez](https://github.com/Rendez) and [@kartik-gupta-ij](https://github.com/kartik-gupta-ij)! - Implement BigInt support + ## 1.7.0 ### Minor Changes - Qdrant v1.7.0 API -- [#54](https://github.com/qdrant/qdrant-js/pull/54) Thanks [@Morad-m11](https://github.com/Morad-m11)! - recommendBatch mispell +- [#54](https://github.com/qdrant/qdrant-js/pull/54) Thanks Mohamed Morad (Morad-m11)! - recommendBatch mispell ## 1.6.0 diff --git a/packages/js-client-grpc/package.json b/packages/js-client-grpc/package.json index 83d173c..7ffd1b8 100644 --- a/packages/js-client-grpc/package.json +++ b/packages/js-client-grpc/package.json @@ -1,6 +1,6 @@ { "name": "@qdrant/js-client-grpc", - "version": "1.7.0", + "version": "1.8.0", "engines": { "node": ">=18.0.0", "pnpm": ">=8" diff --git a/packages/js-client-rest/CHANGELOG.md b/packages/js-client-rest/CHANGELOG.md index ee5d3dd..453ce5b 100644 --- a/packages/js-client-rest/CHANGELOG.md +++ b/packages/js-client-rest/CHANGELOG.md @@ -1,10 +1,18 @@ # @qdrant/js-client-rest +## 1.8.0 + +### Minor Changes + +- Qdrant v1.8.0 API +- [#62](https://github.com/qdrant/qdrant-js/pull/62) Thanks [@Rendez](https://github.com/Rendez) and [@kartik-gupta-ij](https://github.com/kartik-gupta-ij)! - Implement BigInt support + ## 1.7.0 ### Minor Changes - Qdrant v1.7.0 API +- [#54](https://github.com/qdrant/qdrant-js/pull/54) Thanks Mohamed Morad (Morad-m11)! - recommendBatch mispell ## 1.6.0 diff --git a/packages/js-client-rest/package.json b/packages/js-client-rest/package.json index 387a770..5f39251 100644 --- a/packages/js-client-rest/package.json +++ b/packages/js-client-rest/package.json @@ -1,6 +1,6 @@ { "name": "@qdrant/js-client-rest", - "version": "1.7.0", + "version": "1.8.0", "engines": { "node": ">=18.0.0", "pnpm": ">=8" diff --git a/packages/qdrant-js/CHANGELOG.md b/packages/qdrant-js/CHANGELOG.md index 4f4d429..eaf74da 100644 --- a/packages/qdrant-js/CHANGELOG.md +++ b/packages/qdrant-js/CHANGELOG.md @@ -1,5 +1,18 @@ # @qdrant/qdrant-js +## 1.8.0 + +### Minor Changes + +- Qdrant v1.8.0 API + +### Patch Changes + +- [`65`](https://github.com/qdrant/qdrant-js/pull/65) Thanks [@andreban](https://https://github.com/andreban)! - Fix typo in qdrant-js/README.md +- Updated dependencies []: + - @qdrant/js-client-grpc@1.8.0 + - @qdrant/js-client-rest@1.8.0 + ## 1.7.0 ### Minor Changes diff --git a/packages/qdrant-js/package.json b/packages/qdrant-js/package.json index 71e445f..98d47c3 100644 --- a/packages/qdrant-js/package.json +++ b/packages/qdrant-js/package.json @@ -1,6 +1,6 @@ { "name": "@qdrant/qdrant-js", - "version": "1.7.0", + "version": "1.8.0", "engines": { "node": ">=18.0.0", "pnpm": ">=8" @@ -57,8 +57,8 @@ "clean": "rimraf ./dist" }, "dependencies": { - "@qdrant/js-client-rest": "workspace:1.7.0", - "@qdrant/js-client-grpc": "workspace:1.7.0" + "@qdrant/js-client-rest": "workspace:1.8.0", + "@qdrant/js-client-grpc": "workspace:1.8.0" }, "peerDependencies": { "typescript": ">=4.1" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bc15714..46b5869 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -128,10 +128,10 @@ importers: packages/qdrant-js: dependencies: '@qdrant/js-client-grpc': - specifier: workspace:1.7.0 + specifier: workspace:1.8.0 version: link:../js-client-grpc '@qdrant/js-client-rest': - specifier: workspace:1.7.0 + specifier: workspace:1.8.0 version: link:../js-client-rest typescript: specifier: '>=4.1' From 9f1fb4a687720c442c5b8ded4872dadc25cb105b Mon Sep 17 00:00:00 2001 From: Ivan Pleshkov Date: Mon, 4 Mar 2024 19:41:48 +0000 Subject: [PATCH 4/6] remove checksum query path param --- packages/js-client-rest/src/api/snapshots-api.ts | 12 ++++++++++-- .../js-client-rest/src/openapi/generated_schema.ts | 4 ---- packages/js-client-rest/src/qdrant-client.ts | 5 ++--- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/packages/js-client-rest/src/api/snapshots-api.ts b/packages/js-client-rest/src/api/snapshots-api.ts index 5cd50de..be42234 100644 --- a/packages/js-client-rest/src/api/snapshots-api.ts +++ b/packages/js-client-rest/src/api/snapshots-api.ts @@ -47,13 +47,21 @@ export function createSnapshotsApi(client: Client) { */ listSnapshots: client.path('/collections/{collection_name}/snapshots').method('get').create(), + /** + * Recover local collection data from an uploaded snapshot. This will overwrite any data, stored on this node, for the collection. If collection does not exist - it will be created. + */ + recoverFromUploadedSnapshot: client + .path('/collections/{collection_name}/snapshots/upload') + .method('post') + .create({wait: true, priority: true, checksum: true}), + /** * Recover local collection data from a snapshot. This will overwrite any data, stored on this node, for the collection. If collection does not exist - it will be created */ recoverFromSnapshot: client .path('/collections/{collection_name}/snapshots/recover') .method('put') - .create({wait: true, checksum: true}), + .create({wait: true}), /** * Recover shard of a local collection from an uploaded snapshot. This will overwrite any data, stored on this node, for the collection shard @@ -69,7 +77,7 @@ export function createSnapshotsApi(client: Client) { recoverShardFromSnapshot: client .path('/collections/{collection_name}/shards/{shard_id}/snapshots/recover') .method('put') - .create({wait: true, checksum: true}), + .create({wait: true}), /** * Get list of snapshots for a shard of a collection diff --git a/packages/js-client-rest/src/openapi/generated_schema.ts b/packages/js-client-rest/src/openapi/generated_schema.ts index a409d2f..091d659 100644 --- a/packages/js-client-rest/src/openapi/generated_schema.ts +++ b/packages/js-client-rest/src/openapi/generated_schema.ts @@ -3522,8 +3522,6 @@ export interface operations { query?: { /** @description If true, wait for changes to actually happen. If false - let changes happen in background. Default is true. */ wait?: boolean; - /** @description Optional SHA256 checksum to verify snapshot integrity before recovery. */ - checksum?: string; }; path: { /** @description Name of the collection */ @@ -4025,8 +4023,6 @@ export interface operations { query?: { /** @description If true, wait for changes to actually happen. If false - let changes happen in background. Default is true. */ wait?: boolean; - /** @description Optional SHA256 checksum to verify snapshot integrity before recovery. */ - checksum?: string; }; path: { /** @description Name of the collection */ diff --git a/packages/js-client-rest/src/qdrant-client.ts b/packages/js-client-rest/src/qdrant-client.ts index 4b05093..22543b1 100644 --- a/packages/js-client-rest/src/qdrant-client.ts +++ b/packages/js-client-rest/src/qdrant-client.ts @@ -1439,7 +1439,7 @@ export class QdrantClient { collection_name, location, priority, - checksum: checksum === null ? undefined : checksum, + checksum, }); return maybe(response.data.result).orThrow('Recover from snapshot API returned empty'); } @@ -1511,13 +1511,12 @@ export class QdrantClient { async recoverShardFromSnapshot( collection_name: string, shard_id: number, - {wait = true, checksum, ...shard_snapshot_recover}: {wait?: boolean} & SchemaFor<'ShardSnapshotRecover'>, + {wait = true, ...shard_snapshot_recover}: {wait?: boolean} & SchemaFor<'ShardSnapshotRecover'>, ) { const response = await this._openApiClient.snapshots.recoverShardFromSnapshot({ collection_name, shard_id, wait, - checksum: checksum === null ? undefined : checksum, ...shard_snapshot_recover, }); return maybe(response.data.result).orThrow('Recover shard from snapshot returned empty'); From ea2b95d8081dc3565f9439afa017448443cb2a0e Mon Sep 17 00:00:00 2001 From: Ivan Pleshkov Date: Tue, 5 Mar 2024 08:48:51 +0000 Subject: [PATCH 5/6] comments and renamings --- packages/js-client-rest/src/qdrant-client.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/js-client-rest/src/qdrant-client.ts b/packages/js-client-rest/src/qdrant-client.ts index 22543b1..1e9ce0f 100644 --- a/packages/js-client-rest/src/qdrant-client.ts +++ b/packages/js-client-rest/src/qdrant-client.ts @@ -429,6 +429,8 @@ export class QdrantClient { * - 'majority' - query all replicas, but return values present in the majority of replicas * - 'quorum' - query the majority of replicas, return values present in all of them * - 'all' - query all replicas, and return values present in all replicas + * - order_by: + * Order the records by a payload field. * @returns * A pair of (List of points) and (optional offset for the next scroll request). * If next page offset is `None` - there is no more points in the collection to scroll. @@ -906,6 +908,8 @@ export class QdrantClient { * - 'strong' - Write operations go through the permanent leader, * consistent, but may be unavailable if leader is down * - payload: Key-value pairs of payload to assign + * - shard_key: Specify in which shards to look for the points, if not specified - look in all shards + * - key: Assigns payload to each point that satisfy this path of property * - points|filter: List of affected points, filter or points selector. * Example: * - `points: [ @@ -930,6 +934,8 @@ export class QdrantClient { payload, points, filter, + shard_key, + key, wait = true, }: {wait?: boolean; ordering?: SchemaFor<'WriteOrdering'>} & SchemaFor<'SetPayload'>, ) { @@ -938,6 +944,8 @@ export class QdrantClient { payload, points, filter, + shard_key, + key, wait, ordering, }); @@ -1432,6 +1440,8 @@ export class QdrantClient { * - `snapshot` means - prefer snapshot data over the current state * - `replica` means - prefer existing data over the snapshot * Default: `replica` + * - checksum: + * SHA256 checksum to verify snapshot integrity before recovery * @returns True if the snapshot was recovered */ async recoverSnapshot(collection_name: string, {location, priority, checksum}: SchemaFor<'SnapshotRecover'>) { @@ -1723,15 +1733,18 @@ export class QdrantClient { /** * Returns information about the running Qdrant instance * @description Returns information about the running Qdrant instance like version and commit id + * @returns Operation result */ - async root() { + async versionInfo() { const response = await this._openApiClient.service.root({}); - return maybe(response.data.result).orThrow('Root returned empty'); + return maybe(response.data.result).orThrow('Version Info returned empty'); } /** * Check the existence of a collection + * @param collection_name Name of the collection * @description Returns "true" if the given collection name exists, and "false" otherwise + * @returns Operation result */ async collectionExists(collection_name: string) { const response = await this._openApiClient.collections.collectionExists({collection_name}); From 5b07fe572d0811bef5ac8a06b05701ce98e52fb7 Mon Sep 17 00:00:00 2001 From: Ivan Pleshkov Date: Tue, 5 Mar 2024 09:01:31 +0000 Subject: [PATCH 6/6] qdrant version up in integration tests --- packages/qdrant-js/scripts/integration-tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/qdrant-js/scripts/integration-tests.sh b/packages/qdrant-js/scripts/integration-tests.sh index 3f2660a..25b6f77 100755 --- a/packages/qdrant-js/scripts/integration-tests.sh +++ b/packages/qdrant-js/scripts/integration-tests.sh @@ -9,7 +9,7 @@ function stop_docker() docker stop qdrant_test } -QDRANT_LATEST="v1.7.0" +QDRANT_LATEST="v1.8.0" QDRANT_VERSION=${QDRANT_VERSION:-"$QDRANT_LATEST"} QDRANT_HOST='127.0.0.1:6333'