From 0e7f896ef66f72313fe92806e96caf46a7b72acf Mon Sep 17 00:00:00 2001 From: fahreddinozcan Date: Tue, 14 May 2024 15:35:54 +0200 Subject: [PATCH 01/14] feat(command): update command --- src/commands/client/index.ts | 1 + src/commands/client/namespace/index.test.ts | 10 +-- src/commands/client/namespace/index.ts | 29 +++++++- src/commands/client/update/index.test.ts | 34 +++++++++ src/commands/client/update/index.ts | 80 +++++++++++++++++++++ src/commands/client/upsert/index.test.ts | 4 +- src/commands/client/upsert/index.ts | 44 ++++-------- src/commands/command.ts | 1 + src/commands/index.ts | 1 + src/vector.ts | 35 ++++++++- 10 files changed, 195 insertions(+), 44 deletions(-) create mode 100644 src/commands/client/update/index.test.ts create mode 100644 src/commands/client/update/index.ts diff --git a/src/commands/client/index.ts b/src/commands/client/index.ts index 1562c21..477414f 100644 --- a/src/commands/client/index.ts +++ b/src/commands/client/index.ts @@ -6,3 +6,4 @@ export * from "./range"; export * from "./reset"; export * from "./info"; export * from "./namespace"; +export * from "./update"; diff --git a/src/commands/client/namespace/index.test.ts b/src/commands/client/namespace/index.test.ts index 02d3e3a..2dbe772 100644 --- a/src/commands/client/namespace/index.test.ts +++ b/src/commands/client/namespace/index.test.ts @@ -55,18 +55,14 @@ describe("NAMESPACE", () => { metadata: { namespace: "test-namespace-reset" }, }); - sleep(1000); + sleep(5000); - const res = await namespace.query({ - vector: range(0, 384), - topK: 3, - includeMetadata: true, - }); + const res = await namespace.fetch([[1], { includeMetadata: true }]); expect(res.length).toEqual(1); await namespace.reset(); - sleep(1000); + sleep(5000); const res2 = await namespace.query({ vector: range(0, 384), diff --git a/src/commands/client/namespace/index.ts b/src/commands/client/namespace/index.ts index 04ac547..3c14497 100644 --- a/src/commands/client/namespace/index.ts +++ b/src/commands/client/namespace/index.ts @@ -4,6 +4,7 @@ import { QueryCommand, RangeCommand, ResetCommand, + UpdateCommand, UpsertCommand, } from "@commands/client"; import { Dict } from "@commands/client/types"; @@ -59,6 +60,32 @@ export class Namespace { args: CommandArgs> ) => new UpsertCommand(args, { namespace: this.namespace }).exec(this.client); + /* + * Updates specific items in the index. + * It's used for updating existing items in the index. + * + * @example + * ```js + * const updateArgs = { + * id: '123', + * vector: [0.42, 0.87, ...], + * metadata: { property1: 'value1', property2: 'value2' } + * }; + * const updateResult = await index.update(updateArgs); + * console.log(updateResult); // Outputs the result of the update operation + * ``` + * + * @param {CommandArgs} args - The arguments for the upsert command. + * @param {number|string} args.id - The unique identifier for the item being upserted. + * @param {number[]} args.vector - The feature vector associated with the item. + * @param {Record} [args.metadata] - Optional metadata to be associated with the item. + * + * @returns {string} A promise that resolves with the result of the upsert operation after the command is executed. + */ + update = ( + args: CommandArgs> + ) => new UpdateCommand(args, { namespace: this.namespace }).exec(this.client); + /** * Upserts (Updates and Inserts) specific items into the index namespace. * It's used for adding new items to the index namespace or updating existing ones. @@ -81,7 +108,7 @@ export class Namespace { * * @returns {string} A promise that resolves with the result of the upsert operation after the command is executed. */ - fetch = (...args: CommandArgs) => + fetch = (args: CommandArgs) => new FetchCommand(args, { namespace: this.namespace }).exec(this.client); /** diff --git a/src/commands/client/update/index.test.ts b/src/commands/client/update/index.test.ts new file mode 100644 index 0000000..434c648 --- /dev/null +++ b/src/commands/client/update/index.test.ts @@ -0,0 +1,34 @@ +import { afterAll, describe, expect, test } from "bun:test"; +import { FetchCommand, UpdateCommand, UpsertCommand } from "@commands/index"; +import { newHttpClient, range, resetIndexes } from "@utils/test-utils"; +import { sleep } from "bun"; + +const client = newHttpClient(); + +describe("UPSERT", () => { + afterAll(async () => await resetIndexes()); + + test("should update vector metadata", async () => { + await new UpsertCommand({ + id: 1, + vector: range(0, 384), + metadata: { upstash: "test-simple" }, + }).exec(client); + + const res = await new UpdateCommand({ + id: 1, + metadata: { upstash: "test-update" }, + }).exec(client); + + expect(res).toEqual({ updated: 1 }); + + sleep(5000); + + const fetchData = await new FetchCommand<{ upstash: string }>([ + ["1"], + { includeMetadata: true }, + ]).exec(client); + + expect(fetchData[0]?.metadata?.upstash).toBe("test-update"); + }); +}); diff --git a/src/commands/client/update/index.ts b/src/commands/client/update/index.ts new file mode 100644 index 0000000..aae7529 --- /dev/null +++ b/src/commands/client/update/index.ts @@ -0,0 +1,80 @@ +import type { NAMESPACE } from "@commands/client/types"; +import { Command } from "@commands/command"; + +type NoInfer = T extends infer U ? U : never; + +type BasePayload = { + id: number | string; +}; + +type ExtendedVectorPayload = BasePayload & + ( + | { + metadata: NoInfer; + vector?: number[]; + data?: never; + } + | { + metadata?: NoInfer; + vector: number[]; + data?: never; + } + ); + +type ExtendedDataPayload = BasePayload & + ( + | { + metadata: NoInfer; + data: string; + vector?: never; + } + | { + metadata?: NoInfer; + data: string; + vector?: never; + } + ); + +type Payload = + | ExtendedDataPayload + | ExtendedVectorPayload + | ExtendedDataPayload[] + | ExtendedVectorPayload[]; + +type updateCommandOptions = { namespace?: string }; + +type updateEndpointVariants = `update` | `update/${NAMESPACE}`; + +type UpdateCommandResponse = { updated: number }; +export class UpdateCommand extends Command { + constructor(payload: Payload, opts?: updateCommandOptions) { + let endpoint: updateEndpointVariants = "update"; + + if (Array.isArray(payload)) { + const hasData = payload.some((p) => "data" in p && p.data); + if (hasData) { + for (const p of payload) { + if (!("metadata" in p) && "data" in p) { + p.metadata = { + data: p.data, + } as NoInfer; + } + } + } + } else { + if ("data" in payload) { + if (!("metadata" in payload)) { + payload.metadata = { + data: payload.data, + } as NoInfer; + } + } + } + + if (opts?.namespace) { + endpoint = `${endpoint}/${opts.namespace}`; + } + + super(payload, endpoint); + } +} diff --git a/src/commands/client/upsert/index.test.ts b/src/commands/client/upsert/index.test.ts index a26425e..2a92b82 100644 --- a/src/commands/client/upsert/index.test.ts +++ b/src/commands/client/upsert/index.test.ts @@ -73,13 +73,13 @@ describe("UPSERT", () => { await new UpsertCommand([ { id: "hello-world", - //@ts-expect-error Mixed usage of vector and data in the same upsert command is not allowed. + data: "Test1-2-3-4-5", metadata: { upstash: "test" }, }, { id: "hello-world", - + //@ts-expect-error Mixed usage of vector and data in the same upsert command is not allowed. vector: [1, 2, 3, 4], metadata: { upstash: "test" }, }, diff --git a/src/commands/client/upsert/index.ts b/src/commands/client/upsert/index.ts index ebe8aeb..1525b89 100644 --- a/src/commands/client/upsert/index.ts +++ b/src/commands/client/upsert/index.ts @@ -3,43 +3,23 @@ import { Command } from "@commands/command"; type NoInfer = T extends infer U ? U : never; -type BasePayload = { +type VectorPayload = { id: number | string; + vector: number[]; + metadata?: NoInfer; }; -type ExtendedVectorPayload = BasePayload & - ( - | { - metadata: NoInfer; - vector?: number[]; - data?: never; - } - | { - metadata?: NoInfer; - vector: number[]; - data?: never; - } - ); - -type ExtendedDataPayload = BasePayload & - ( - | { - metadata: NoInfer; - data: string; - vector?: never; - } - | { - metadata?: NoInfer; - data: string; - vector?: never; - } - ); +type DataPayload = { + id: number | string; + data: string; + metadata?: NoInfer; +}; type Payload = - | ExtendedDataPayload - | ExtendedVectorPayload - | ExtendedDataPayload[] - | ExtendedVectorPayload[]; + | VectorPayload + | DataPayload + | VectorPayload[] + | DataPayload[]; type UpsertCommandOptions = { namespace?: string }; diff --git a/src/commands/command.ts b/src/commands/command.ts index df31d2c..5b1ddbd 100644 --- a/src/commands/command.ts +++ b/src/commands/command.ts @@ -5,6 +5,7 @@ import { NAMESPACE } from "./client/types"; const ENDPOINTS = [ "upsert", + "update", "query", "delete", "fetch", diff --git a/src/commands/index.ts b/src/commands/index.ts index da38475..a0e4c48 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -3,6 +3,7 @@ export * from "./client/delete"; export * from "./client/fetch"; export * from "./client/query"; export * from "./client/upsert"; +export * from "./client/update"; export * from "./client/reset"; export * from "./client/range"; export * from "./client/info"; diff --git a/src/vector.ts b/src/vector.ts index a3e620b..91371b5 100644 --- a/src/vector.ts +++ b/src/vector.ts @@ -6,6 +6,7 @@ import { QueryCommand, RangeCommand, ResetCommand, + UpdateCommand, UpsertCommand, } from "@commands/client"; import { Dict } from "@commands/client/types"; @@ -107,6 +108,34 @@ export class Index { options?: { namespace?: string } ) => new UpsertCommand(args, options).exec(this.client); + /* + * Updates specific items in the index. + * It's used for updating existing items in the index. + * + * @example + * ```js + * const updateArgs = { + * id: '123', + * vector: [0.42, 0.87, ...], + * metadata: { property1: 'value1', property2: 'value2' } + * }; + * const updateResult = await index.update(updateArgs); + * console.log(updateResult); // Outputs the result of the update operation + * ``` + * + * @param {CommandArgs} args - The arguments for the upsert command. + * @param {number|string} args.id - The unique identifier for the item being upserted. + * @param {number[]} args.vector - The feature vector associated with the item. + * @param {Record} [args.metadata] - Optional metadata to be associated with the item. + * @param {string} [args.namespace] - The namespace to update the item in. + * + * @returns {string} A promise that resolves with the result of the upsert operation after the command is executed. + */ + update = ( + args: CommandArgs>, + options?: { namespace?: string } + ) => new UpdateCommand(args, options).exec(this.client); + /** * It's used for retrieving specific items from the index, optionally including * their metadata and feature vectors. @@ -127,8 +156,10 @@ export class Index { * * @returns {Promise[]>} A promise that resolves with an array of fetched items or null if not found, after the command is executed. */ - fetch = (...args: CommandArgs) => - new FetchCommand(args).exec(this.client); + fetch = ( + args: CommandArgs, + options?: { namespace: string } + ) => new FetchCommand(args, options).exec(this.client); /** * It's used for wiping an entire index. From 155ee8c913c7f987e52d8512e0bc60598a6c8728 Mon Sep 17 00:00:00 2001 From: fahreddinozcan Date: Tue, 14 May 2024 15:46:24 +0200 Subject: [PATCH 02/14] remove reduntant metadata update --- src/commands/client/update/index.ts | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/commands/client/update/index.ts b/src/commands/client/update/index.ts index aae7529..bf21b51 100644 --- a/src/commands/client/update/index.ts +++ b/src/commands/client/update/index.ts @@ -50,27 +50,6 @@ export class UpdateCommand extends Command { constructor(payload: Payload, opts?: updateCommandOptions) { let endpoint: updateEndpointVariants = "update"; - if (Array.isArray(payload)) { - const hasData = payload.some((p) => "data" in p && p.data); - if (hasData) { - for (const p of payload) { - if (!("metadata" in p) && "data" in p) { - p.metadata = { - data: p.data, - } as NoInfer; - } - } - } - } else { - if ("data" in payload) { - if (!("metadata" in payload)) { - payload.metadata = { - data: payload.data, - } as NoInfer; - } - } - } - if (opts?.namespace) { endpoint = `${endpoint}/${opts.namespace}`; } From dea2af768bb73edf6ca934b2e07ec60f38424695 Mon Sep 17 00:00:00 2001 From: fahreddinozcan Date: Tue, 14 May 2024 15:50:50 +0200 Subject: [PATCH 03/14] fix update jsdocs and return type --- src/commands/client/namespace/index.ts | 8 ++++---- src/vector.ts | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/commands/client/namespace/index.ts b/src/commands/client/namespace/index.ts index 3c14497..e7ba6d2 100644 --- a/src/commands/client/namespace/index.ts +++ b/src/commands/client/namespace/index.ts @@ -75,15 +75,15 @@ export class Namespace { * console.log(updateResult); // Outputs the result of the update operation * ``` * - * @param {CommandArgs} args - The arguments for the upsert command. - * @param {number|string} args.id - The unique identifier for the item being upserted. + * @param {CommandArgs} args - The arguments for the upsert command. + * @param {number|string} args.id - The unique identifier for the item being updated. * @param {number[]} args.vector - The feature vector associated with the item. * @param {Record} [args.metadata] - Optional metadata to be associated with the item. * - * @returns {string} A promise that resolves with the result of the upsert operation after the command is executed. + * @returns {string} A promise that resolves with the result of the update operation after the command is executed. */ update = ( - args: CommandArgs> + args: CommandArgs> ) => new UpdateCommand(args, { namespace: this.namespace }).exec(this.client); /** diff --git a/src/vector.ts b/src/vector.ts index 91371b5..9b7be6e 100644 --- a/src/vector.ts +++ b/src/vector.ts @@ -123,16 +123,16 @@ export class Index { * console.log(updateResult); // Outputs the result of the update operation * ``` * - * @param {CommandArgs} args - The arguments for the upsert command. - * @param {number|string} args.id - The unique identifier for the item being upserted. + * @param {CommandArgs} args - The arguments for the update command. + * @param {number|string} args.id - The unique identifier for the item being updated. * @param {number[]} args.vector - The feature vector associated with the item. * @param {Record} [args.metadata] - Optional metadata to be associated with the item. * @param {string} [args.namespace] - The namespace to update the item in. * - * @returns {string} A promise that resolves with the result of the upsert operation after the command is executed. + * @returns {string} A promise that resolves with the result of the update operation after the command is executed. */ update = ( - args: CommandArgs>, + args: CommandArgs>, options?: { namespace?: string } ) => new UpdateCommand(args, options).exec(this.client); From 28048983052815d5ae13f166cd8ee9876d0e63db Mon Sep 17 00:00:00 2001 From: fahreddinozcan Date: Tue, 14 May 2024 15:52:47 +0200 Subject: [PATCH 04/14] fix jsdocs --- src/commands/client/namespace/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/client/namespace/index.ts b/src/commands/client/namespace/index.ts index e7ba6d2..bda735b 100644 --- a/src/commands/client/namespace/index.ts +++ b/src/commands/client/namespace/index.ts @@ -75,7 +75,7 @@ export class Namespace { * console.log(updateResult); // Outputs the result of the update operation * ``` * - * @param {CommandArgs} args - The arguments for the upsert command. + * @param {CommandArgs} args - The arguments for the update command. * @param {number|string} args.id - The unique identifier for the item being updated. * @param {number[]} args.vector - The feature vector associated with the item. * @param {Record} [args.metadata] - Optional metadata to be associated with the item. From b5efdbb8a9ba105ae97b489edc029533f84052ec Mon Sep 17 00:00:00 2001 From: fahreddinozcan Date: Tue, 14 May 2024 20:16:22 +0200 Subject: [PATCH 05/14] fix fetch command --- src/commands/client/fetch/index.test.ts | 14 ++++ src/commands/client/fetch/index.ts | 11 ++-- src/commands/client/namespace/index.ts | 81 ++++++++++++------------ src/commands/client/update/index.test.ts | 22 ++++++- src/vector.ts | 6 +- 5 files changed, 83 insertions(+), 51 deletions(-) diff --git a/src/commands/client/fetch/index.test.ts b/src/commands/client/fetch/index.test.ts index 0252f33..d091c91 100644 --- a/src/commands/client/fetch/index.test.ts +++ b/src/commands/client/fetch/index.test.ts @@ -1,6 +1,7 @@ import { afterAll, describe, expect, test } from "bun:test"; import { FetchCommand, UpsertCommand } from "@commands/index"; import { newHttpClient, randomID, range, resetIndexes } from "@utils/test-utils"; +import { Index } from "../../../../index"; const client = newHttpClient(); @@ -54,4 +55,17 @@ describe("FETCH", () => { expect(res).toEqual([mockData]); }); + + test("successfully fetches with the existing interface", async () => { + const index = new Index({ + url: process.env.UPSTASH_VECTOR_REST_URL!, + token: process.env.UPSTASH_VECTOR_REST_TOKEN!, + }); + + const res = await index.fetch([randomID()], { includeMetadata: true, namespace: "ns" }); + + expect(res).toEqual([null]); + + + }); }); diff --git a/src/commands/client/fetch/index.ts b/src/commands/client/fetch/index.ts index ea83009..bf2578a 100644 --- a/src/commands/client/fetch/index.ts +++ b/src/commands/client/fetch/index.ts @@ -5,6 +5,7 @@ import { Command } from "@commands/command"; type FetchCommandOptions = { includeMetadata?: boolean; includeVectors?: boolean; + namespace?: string; }; export type FetchResult = Vector | null; @@ -12,14 +13,12 @@ export type FetchResult = Vector | null; type FetchEndpointVariants = `fetch` | `fetch/${NAMESPACE}`; export class FetchCommand extends Command[]> { - constructor( - [ids, opts]: [ids: number[] | string[], opts?: FetchCommandOptions], - options?: { namespace?: string } - ) { + constructor([ids, opts]: [ids: number[] | string[], opts?: FetchCommandOptions]) { let endpoint: FetchEndpointVariants = "fetch"; - if (options?.namespace) { - endpoint = `${endpoint}/${options.namespace}`; + if (opts?.namespace) { + endpoint = `${endpoint}/${opts.namespace}`; + delete opts.namespace; } super({ ids, ...opts }, endpoint); diff --git a/src/commands/client/namespace/index.ts b/src/commands/client/namespace/index.ts index bda735b..96364a3 100644 --- a/src/commands/client/namespace/index.ts +++ b/src/commands/client/namespace/index.ts @@ -34,27 +34,27 @@ export class Namespace { } /** - * Queries an index namespace with specified parameters. - * This method creates and executes a query command on an index based on the provided arguments. + * Upserts (Updates and Inserts) specific items into the index namespace. + * It's used for adding new items to the index namespace or updating existing ones. * * @example * ```js - * await index.namespace("ns").query({ - * topK: 3, - * vector: [ 0.22, 0.66 ], - * filter: "age >= 23 and (type = \'turtle\' OR type = \'cat\')" - * }); + * const upsertArgs = { + * id: '123', + * vector: [0.42, 0.87, ...], + * metadata: { property1: 'value1', property2: 'value2' } + * }; + * const upsertResult = await index.namespace("ns").upsert(upsertArgs); + * console.log(upsertResult); // Outputs the result of the upsert operation * ``` * - * @param {Object} args - The arguments for the query command. - * @param {number[]} args.vector - An array of numbers representing the feature vector for the query. - * This vector is utilized to find the most relevant items in the index. - * @param {number} args.topK - The desired number of top results to be returned, based on relevance or similarity to the query vector. - * @param {string} [args.filter] - An optional filter string to be used in the query. The filter string is used to narrow down the query results. - * @param {boolean} [args.includeVectors=false] - When set to true, includes the feature vectors of the returned items in the response. - * @param {boolean} [args.includeMetadata=false] - When set to true, includes additional metadata of the returned items in the response. + * @param {CommandArgs} args - The arguments for the upsert command. + * @param {number|string} args.id - The unique identifier for the item being upserted. + * @param {number[]} args.vector - The feature vector associated with the item. + * @param {Dict} [args.metadata] - Optional metadata to be associated with the item. + * @param {string} [args.namespace] - The namespace to fetch the item from. * - * @returns A promise that resolves with an array of query result objects when the request to query the index is completed. + * @returns {string} A promise that resolves with the result of the upsert operation after the command is executed. */ upsert = ( args: CommandArgs> @@ -86,31 +86,6 @@ export class Namespace { args: CommandArgs> ) => new UpdateCommand(args, { namespace: this.namespace }).exec(this.client); - /** - * Upserts (Updates and Inserts) specific items into the index namespace. - * It's used for adding new items to the index namespace or updating existing ones. - * - * @example - * ```js - * const upsertArgs = { - * id: '123', - * vector: [0.42, 0.87, ...], - * metadata: { property1: 'value1', property2: 'value2' } - * }; - * const upsertResult = await index.namespace("ns").upsert(upsertArgs); - * console.log(upsertResult); // Outputs the result of the upsert operation - * ``` - * - * @param {CommandArgs} args - The arguments for the upsert command. - * @param {number|string} args.id - The unique identifier for the item being upserted. - * @param {number[]} args.vector - The feature vector associated with the item. - * @param {Dict} [args.metadata] - Optional metadata to be associated with the item. - * - * @returns {string} A promise that resolves with the result of the upsert operation after the command is executed. - */ - fetch = (args: CommandArgs) => - new FetchCommand(args, { namespace: this.namespace }).exec(this.client); - /** * It's used for retrieving specific items from the index namespace, optionally including * their metadata and feature vectors. @@ -131,6 +106,32 @@ export class Namespace { * * @returns {Promise[]>} A promise that resolves with an array of fetched items or null if not found, after the command is executed. */ + fetch = (...args: CommandArgs) => + new FetchCommand(args).exec(this.client); + + /** + * Queries an index namespace with specified parameters. + * This method creates and executes a query command on an index based on the provided arguments. + * + * @example + * ```js + * await index.namespace("ns").query({ + * topK: 3, + * vector: [ 0.22, 0.66 ], + * filter: "age >= 23 and (type = \'turtle\' OR type = \'cat\')" + * }); + * ``` + * + * @param {Object} args - The arguments for the query command. + * @param {number[]} args.vector - An array of numbers representing the feature vector for the query. + * This vector is utilized to find the most relevant items in the index. + * @param {number} args.topK - The desired number of top results to be returned, based on relevance or similarity to the query vector. + * @param {string} [args.filter] - An optional filter string to be used in the query. The filter string is used to narrow down the query results. + * @param {boolean} [args.includeVectors=false] - When set to true, includes the feature vectors of the returned items in the response. + * @param {boolean} [args.includeMetadata=false] - When set to true, includes additional metadata of the returned items in the response. + * + * @returns A promise that resolves with an array of query result objects when the request to query the index is completed. + */ query = (args: CommandArgs) => new QueryCommand(args, { namespace: this.namespace }).exec(this.client); diff --git a/src/commands/client/update/index.test.ts b/src/commands/client/update/index.test.ts index 434c648..8367410 100644 --- a/src/commands/client/update/index.test.ts +++ b/src/commands/client/update/index.test.ts @@ -2,10 +2,11 @@ import { afterAll, describe, expect, test } from "bun:test"; import { FetchCommand, UpdateCommand, UpsertCommand } from "@commands/index"; import { newHttpClient, range, resetIndexes } from "@utils/test-utils"; import { sleep } from "bun"; +import { Index } from "../../../../index"; const client = newHttpClient(); -describe("UPSERT", () => { +describe("UPDATE", () => { afterAll(async () => await resetIndexes()); test("should update vector metadata", async () => { @@ -31,4 +32,23 @@ describe("UPSERT", () => { expect(fetchData[0]?.metadata?.upstash).toBe("test-update"); }); + + test("successfully updates with index", async () => { + const index = new Index({ + url: process.env.UPSTASH_VECTOR_REST_URL!, + token: process.env.UPSTASH_VECTOR_REST_TOKEN!, + }); + + await index.upsert([{ + id: 'test', + vector: range(0, 384), + metadata: { upstash: "test-simple" }, + }]) + + sleep(5000); + + const res = await index.update([{ id: "test", metadata: { upstash: "test-update" } }]); + + expect(res).toEqual({ updated: 1 }); + }); }); diff --git a/src/vector.ts b/src/vector.ts index 9b7be6e..d91d6d9 100644 --- a/src/vector.ts +++ b/src/vector.ts @@ -156,10 +156,8 @@ export class Index { * * @returns {Promise[]>} A promise that resolves with an array of fetched items or null if not found, after the command is executed. */ - fetch = ( - args: CommandArgs, - options?: { namespace: string } - ) => new FetchCommand(args, options).exec(this.client); + fetch = (...args: CommandArgs) => + new FetchCommand(args).exec(this.client); /** * It's used for wiping an entire index. From 27a6c8c321e39d30c2a24b55890c58b0a6446e40 Mon Sep 17 00:00:00 2001 From: fahreddinozcan Date: Wed, 15 May 2024 16:20:10 +0200 Subject: [PATCH 06/14] batch update requests manually --- src/commands/client/namespace/index.test.ts | 2 +- src/commands/client/update/index.test.ts | 30 +++++++++-- src/commands/client/update/index.ts | 57 ++++++++------------- src/commands/client/upsert/index.test.ts | 25 ++++++++- src/http/index.ts | 1 + src/vector.ts | 16 +++++- 6 files changed, 86 insertions(+), 45 deletions(-) diff --git a/src/commands/client/namespace/index.test.ts b/src/commands/client/namespace/index.test.ts index 2dbe772..a13f2dd 100644 --- a/src/commands/client/namespace/index.test.ts +++ b/src/commands/client/namespace/index.test.ts @@ -57,7 +57,7 @@ describe("NAMESPACE", () => { sleep(5000); - const res = await namespace.fetch([[1], { includeMetadata: true }]); + const res = await namespace.fetch([1], { includeMetadata: true }); expect(res.length).toEqual(1); await namespace.reset(); diff --git a/src/commands/client/update/index.test.ts b/src/commands/client/update/index.test.ts index 9f43401..e5eac7a 100644 --- a/src/commands/client/update/index.test.ts +++ b/src/commands/client/update/index.test.ts @@ -33,7 +33,7 @@ describe("UPDATE", () => { expect(fetchData[0]?.metadata?.upstash).toBe("test-update"); }); - test("successfully updates with index", async () => { + test("successfully updates a batch of vectors", async () => { const index = new Index({ url: process.env.UPSTASH_VECTOR_REST_URL!, token: process.env.UPSTASH_VECTOR_REST_TOKEN!, @@ -41,16 +41,36 @@ describe("UPDATE", () => { await index.upsert([ { - id: "test", + id: "test-1", vector: range(0, 384), - metadata: { upstash: "test-simple" }, + metadata: { upstash: "test-1-not-updated" }, + }, + { + id: "test-2", + vector: range(0, 384), + metadata: { upstash: "test-2-not-updated" }, }, ]); sleep(5000); - const res = await index.update([{ id: "test", metadata: { upstash: "test-update" } }]); + const res = await index.update([ + { + id: "test-1", + metadata: { upstash: "test-1-updated" }, + }, + { + id: "test-2", + metadata: { upstash: "test-2-updated" }, + }, + ]); + + expect(res).toEqual({ updated: 2 }); - expect(res).toEqual({ updated: 1 }); + sleep(2000); + + const fetchData = await index.fetch(["test-1", "test-2"], { includeMetadata: true }); + + expect(fetchData[0]?.metadata?.upstash).toBe("test-1-updated"); }); }); diff --git a/src/commands/client/update/index.ts b/src/commands/client/update/index.ts index bf21b51..72baaba 100644 --- a/src/commands/client/update/index.ts +++ b/src/commands/client/update/index.ts @@ -3,52 +3,35 @@ import { Command } from "@commands/command"; type NoInfer = T extends infer U ? U : never; -type BasePayload = { - id: number | string; +type MetadataUpdatePayload = { + id: string | number; + metadata: NoInfer; }; -type ExtendedVectorPayload = BasePayload & - ( - | { - metadata: NoInfer; - vector?: number[]; - data?: never; - } - | { - metadata?: NoInfer; - vector: number[]; - data?: never; - } - ); - -type ExtendedDataPayload = BasePayload & - ( - | { - metadata: NoInfer; - data: string; - vector?: never; - } - | { - metadata?: NoInfer; - data: string; - vector?: never; - } - ); +type VectorUpdatePayload = { + id: string | number; + vector: number[]; +}; + +type DataUpdatePayload = { + id: string | number; + data: string; +}; type Payload = - | ExtendedDataPayload - | ExtendedVectorPayload - | ExtendedDataPayload[] - | ExtendedVectorPayload[]; + | MetadataUpdatePayload + | VectorUpdatePayload + | DataUpdatePayload + | (MetadataUpdatePayload | VectorUpdatePayload | DataUpdatePayload)[]; -type updateCommandOptions = { namespace?: string }; +type UpdateCommandOptions = { namespace?: string }; -type updateEndpointVariants = `update` | `update/${NAMESPACE}`; +type UpdateEndpointVariants = `update` | `update/${NAMESPACE}`; type UpdateCommandResponse = { updated: number }; export class UpdateCommand extends Command { - constructor(payload: Payload, opts?: updateCommandOptions) { - let endpoint: updateEndpointVariants = "update"; + constructor(payload: Payload, opts?: UpdateCommandOptions) { + let endpoint: UpdateEndpointVariants = "update"; if (opts?.namespace) { endpoint = `${endpoint}/${opts.namespace}`; diff --git a/src/commands/client/upsert/index.test.ts b/src/commands/client/upsert/index.test.ts index 2a92b82..033c7b1 100644 --- a/src/commands/client/upsert/index.test.ts +++ b/src/commands/client/upsert/index.test.ts @@ -1,10 +1,15 @@ import { afterAll, describe, expect, test } from "bun:test"; import { FetchCommand, UpsertCommand } from "@commands/index"; -import { newHttpClient, range, resetIndexes } from "@utils/test-utils"; +import { newHttpClient, randomID, range, resetIndexes } from "@utils/test-utils"; +import { Index } from "../../../../index"; const client = newHttpClient(); describe("UPSERT", () => { + const index = new Index({ + url: process.env.UPSTASH_VECTOR_REST_URL!, + token: process.env.UPSTASH_VECTOR_REST_TOKEN!, + }); afterAll(async () => await resetIndexes()); test("should add record successfully", async () => { @@ -110,4 +115,22 @@ describe("UPSERT", () => { expect(resUpsert).toEqual("Success"); }); + + test("should run with index.upsert in bulk", async () => { + const upsertData = [ + { + id: randomID(), + vector: range(0, 384), + metadata: { upstash: "test-simple-1" }, + }, + { + id: randomID(), + vector: range(0, 384), + metadata: { upstash: "test-simple-2" }, + }, + ]; + const resUpsert = await index.upsert(upsertData, { namespace: "test-namespace" }); + + expect(resUpsert).toEqual("Success"); + }); }); diff --git a/src/http/index.ts b/src/http/index.ts index 97b2b46..6dc98c8 100644 --- a/src/http/index.ts +++ b/src/http/index.ts @@ -105,6 +105,7 @@ export class HttpClient implements Requester { } public async request(req: UpstashRequest): Promise> { + // console.log(JSON.stringify(req.body)) const requestOptions = { cache: this.options.cache, method: "POST", diff --git a/src/vector.ts b/src/vector.ts index d91d6d9..cabc7e4 100644 --- a/src/vector.ts +++ b/src/vector.ts @@ -134,7 +134,21 @@ export class Index { update = ( args: CommandArgs>, options?: { namespace?: string } - ) => new UpdateCommand(args, options).exec(this.client); + ) => { + if (Array.isArray(args)) { + let successfulUpdates = 0; + const promises = args.map((element) => { + const command = new UpdateCommand(element, options); + + return command.exec(this.client).then(() => { + successfulUpdates++; + }); + }); + + return Promise.all(promises).then(() => ({ updated: successfulUpdates })); + } + return new UpdateCommand(args, options).exec(this.client); + }; /** * It's used for retrieving specific items from the index, optionally including From 12f40f1856bedb6f21f83ece040b0a92307fb76d Mon Sep 17 00:00:00 2001 From: fahreddinozcan Date: Wed, 15 May 2024 16:24:19 +0200 Subject: [PATCH 07/14] batch namespace update requests --- src/commands/client/namespace/index.test.ts | 43 +++++++++++++++++++++ src/commands/client/namespace/index.ts | 18 ++++++++- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/commands/client/namespace/index.test.ts b/src/commands/client/namespace/index.test.ts index a13f2dd..161536c 100644 --- a/src/commands/client/namespace/index.test.ts +++ b/src/commands/client/namespace/index.test.ts @@ -72,4 +72,47 @@ describe("NAMESPACE", () => { expect(res2.length).toEqual(0); }); + + test("should update vector in namespace", async () => { + const index = new Index({ + url: process.env.UPSTASH_VECTOR_REST_URL!, + token: process.env.UPSTASH_VECTOR_REST_TOKEN!, + }); + + const namespace = index.namespace("test-namespace-update"); + + await namespace.upsert([ + { + id: "test-1", + vector: range(0, 384), + metadata: { upstash: "test-1-not-updated" }, + }, + { + id: "test-2", + vector: range(0, 384), + metadata: { upstash: "test-2-not-updated" }, + }, + ]); + + sleep(5000); + + const res = await namespace.update([ + { + id: "test-1", + metadata: { upstash: "test-1-updated" }, + }, + { + id: "test-2", + metadata: { upstash: "test-2-updated" }, + }, + ]); + + expect(res).toEqual({ updated: 2 }); + + sleep(2000); + + const fetchData = await namespace.fetch(["test-1", "test-2"], { includeMetadata: true }); + + expect(fetchData[0]?.metadata?.upstash).toBe("test-1-updated"); + }); }); diff --git a/src/commands/client/namespace/index.ts b/src/commands/client/namespace/index.ts index 136309d..08101e1 100644 --- a/src/commands/client/namespace/index.ts +++ b/src/commands/client/namespace/index.ts @@ -82,8 +82,22 @@ export class Namespace { * @returns {string} A promise that resolves with the result of the update operation after the command is executed. */ update = ( - args: CommandArgs> - ) => new UpdateCommand(args, { namespace: this.namespace }).exec(this.client); + args: CommandArgs>, + ) => { + if (Array.isArray(args)) { + let successfulUpdates = 0; + const promises = args.map((element) => { + const command = new UpdateCommand(element, { namespace: this.namespace }); + + return command.exec(this.client).then(() => { + successfulUpdates++; + }); + }); + + return Promise.all(promises).then(() => ({ updated: successfulUpdates })); + } + return new UpdateCommand(args, { namespace: this.namespace }).exec(this.client); + }; /** * It's used for retrieving specific items from the index namespace, optionally including From 6f0c733a0ef30a9ad47c3136ecc959831acb823c Mon Sep 17 00:00:00 2001 From: fahreddinozcan Date: Wed, 15 May 2024 16:26:09 +0200 Subject: [PATCH 08/14] fmt --- src/commands/client/namespace/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/client/namespace/index.ts b/src/commands/client/namespace/index.ts index 08101e1..6ea7bcf 100644 --- a/src/commands/client/namespace/index.ts +++ b/src/commands/client/namespace/index.ts @@ -82,7 +82,7 @@ export class Namespace { * @returns {string} A promise that resolves with the result of the update operation after the command is executed. */ update = ( - args: CommandArgs>, + args: CommandArgs> ) => { if (Array.isArray(args)) { let successfulUpdates = 0; From 009340d53fa47925c68bc839c6d36f58e5c469fc Mon Sep 17 00:00:00 2001 From: fahreddinozcan Date: Wed, 22 May 2024 10:56:13 +0200 Subject: [PATCH 09/14] cancel and revert array update method --- src/commands/client/namespace/index.test.ts | 27 ++++-------- src/commands/client/query/index.test.ts | 10 ++--- src/commands/client/update/index.test.ts | 47 +-------------------- src/commands/client/update/index.ts | 3 +- 4 files changed, 16 insertions(+), 71 deletions(-) diff --git a/src/commands/client/namespace/index.test.ts b/src/commands/client/namespace/index.test.ts index 53309b0..dbd1e25 100644 --- a/src/commands/client/namespace/index.test.ts +++ b/src/commands/client/namespace/index.test.ts @@ -84,31 +84,20 @@ describe("NAMESPACE", () => { vector: range(0, 384), metadata: { upstash: "test-1-not-updated" }, }, - { - id: "test-2", - vector: range(0, 384), - metadata: { upstash: "test-2-not-updated" }, - }, ]); - sleep(5000); + awaitUntilIndexed(index); - const res = await namespace.update([ - { - id: "test-1", - metadata: { upstash: "test-1-updated" }, - }, - { - id: "test-2", - metadata: { upstash: "test-2-updated" }, - }, - ]); + const res = await namespace.update({ + id: "test-1", + metadata: { upstash: "test-1-updated" }, + }); - expect(res).toEqual({ updated: 2 }); + expect(res).toEqual({ updated: 1 }); - sleep(2000); + awaitUntilIndexed(index); - const fetchData = await namespace.fetch(["test-1", "test-2"], { includeMetadata: true }); + const fetchData = await namespace.fetch(["test-1"], { includeMetadata: true }); expect(fetchData[0]?.metadata?.upstash).toBe("test-1-updated"); }); diff --git a/src/commands/client/query/index.test.ts b/src/commands/client/query/index.test.ts index cd3d7b1..cb019ea 100644 --- a/src/commands/client/query/index.test.ts +++ b/src/commands/client/query/index.test.ts @@ -126,7 +126,7 @@ describe("QUERY", () => { await new UpsertCommand([ { id: "hello-world", - data: "Test1-2-3-4-5", + data: "testing-plan-text", metadata: { upstash: "test" }, }, ]).exec(embeddingClient); @@ -134,7 +134,7 @@ describe("QUERY", () => { await awaitUntilIndexed(embeddingClient); const res = await new QueryCommand({ - data: "Test1-2-3-4-5", + data: "testing-plain-text", topK: 1, includeVectors: true, includeMetadata: true, @@ -156,12 +156,12 @@ describe("QUERY", () => { await new UpsertCommand([ { id: "hello-world", - data: "Test1-2-3-4-5", + data: "testing-bulk-data-original", metadata: { upstash: "Cookie" }, }, { id: "hello-world1", - data: "Test1-2-3-4-5-6", + data: "testing-bulk-data-secondary", metadata: { upstash: "Monster" }, }, ]).exec(embeddingClient); @@ -169,7 +169,7 @@ describe("QUERY", () => { await awaitUntilIndexed(embeddingClient); const res = await new QueryCommand({ - data: "Test1-2-3-4-5", + data: "testing-bulk-data-original", topK: 1, includeVectors: true, includeMetadata: true, diff --git a/src/commands/client/update/index.test.ts b/src/commands/client/update/index.test.ts index e5eac7a..75d6c19 100644 --- a/src/commands/client/update/index.test.ts +++ b/src/commands/client/update/index.test.ts @@ -1,8 +1,6 @@ import { afterAll, describe, expect, test } from "bun:test"; import { FetchCommand, UpdateCommand, UpsertCommand } from "@commands/index"; -import { newHttpClient, range, resetIndexes } from "@utils/test-utils"; -import { sleep } from "bun"; -import { Index } from "../../../../index"; +import { awaitUntilIndexed, newHttpClient, range, resetIndexes } from "@utils/test-utils"; const client = newHttpClient(); @@ -23,7 +21,7 @@ describe("UPDATE", () => { expect(res).toEqual({ updated: 1 }); - sleep(5000); + await awaitUntilIndexed(client, 5000); const fetchData = await new FetchCommand<{ upstash: string }>([ ["1"], @@ -32,45 +30,4 @@ describe("UPDATE", () => { expect(fetchData[0]?.metadata?.upstash).toBe("test-update"); }); - - test("successfully updates a batch of vectors", async () => { - const index = new Index({ - url: process.env.UPSTASH_VECTOR_REST_URL!, - token: process.env.UPSTASH_VECTOR_REST_TOKEN!, - }); - - await index.upsert([ - { - id: "test-1", - vector: range(0, 384), - metadata: { upstash: "test-1-not-updated" }, - }, - { - id: "test-2", - vector: range(0, 384), - metadata: { upstash: "test-2-not-updated" }, - }, - ]); - - sleep(5000); - - const res = await index.update([ - { - id: "test-1", - metadata: { upstash: "test-1-updated" }, - }, - { - id: "test-2", - metadata: { upstash: "test-2-updated" }, - }, - ]); - - expect(res).toEqual({ updated: 2 }); - - sleep(2000); - - const fetchData = await index.fetch(["test-1", "test-2"], { includeMetadata: true }); - - expect(fetchData[0]?.metadata?.upstash).toBe("test-1-updated"); - }); }); diff --git a/src/commands/client/update/index.ts b/src/commands/client/update/index.ts index 72baaba..5047787 100644 --- a/src/commands/client/update/index.ts +++ b/src/commands/client/update/index.ts @@ -21,8 +21,7 @@ type DataUpdatePayload = { type Payload = | MetadataUpdatePayload | VectorUpdatePayload - | DataUpdatePayload - | (MetadataUpdatePayload | VectorUpdatePayload | DataUpdatePayload)[]; + | DataUpdatePayload; type UpdateCommandOptions = { namespace?: string }; From cb1f27526a293b176f6fc6976bf5d61a43770449 Mon Sep 17 00:00:00 2001 From: fahreddinozcan Date: Wed, 22 May 2024 10:59:50 +0200 Subject: [PATCH 10/14] cleanup: comment --- src/http/index.ts | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/http/index.ts b/src/http/index.ts index 6dc98c8..c448e80 100644 --- a/src/http/index.ts +++ b/src/http/index.ts @@ -28,22 +28,22 @@ export interface Requester { export type RetryConfig = | false | { - /** - * The number of retries to attempt before giving up. - * - * @default 5 - */ - retries?: number; - /** - * A backoff function receives the current retry cound and returns a number in milliseconds to wait before retrying. - * - * @default - * ```ts - * Math.exp(retryCount) * 50 - * ``` - */ - backoff?: (retryCount: number) => number; - }; + /** + * The number of retries to attempt before giving up. + * + * @default 5 + */ + retries?: number; + /** + * A backoff function receives the current retry cound and returns a number in milliseconds to wait before retrying. + * + * @default + * ```ts + * Math.exp(retryCount) * 50 + * ``` + */ + backoff?: (retryCount: number) => number; + }; export type RequesterConfig = { /** @@ -105,7 +105,6 @@ export class HttpClient implements Requester { } public async request(req: UpstashRequest): Promise> { - // console.log(JSON.stringify(req.body)) const requestOptions = { cache: this.options.cache, method: "POST", From 91a519c14aed4847d0a922971faa0570c9bcdbcb Mon Sep 17 00:00:00 2001 From: fahreddinozcan Date: Wed, 22 May 2024 11:03:59 +0200 Subject: [PATCH 11/14] refactor update methods --- src/commands/client/namespace/index.ts | 16 +------------ src/http/index.ts | 32 +++++++++++++------------- src/vector.ts | 16 +------------ 3 files changed, 18 insertions(+), 46 deletions(-) diff --git a/src/commands/client/namespace/index.ts b/src/commands/client/namespace/index.ts index 6ea7bcf..136309d 100644 --- a/src/commands/client/namespace/index.ts +++ b/src/commands/client/namespace/index.ts @@ -83,21 +83,7 @@ export class Namespace { */ update = ( args: CommandArgs> - ) => { - if (Array.isArray(args)) { - let successfulUpdates = 0; - const promises = args.map((element) => { - const command = new UpdateCommand(element, { namespace: this.namespace }); - - return command.exec(this.client).then(() => { - successfulUpdates++; - }); - }); - - return Promise.all(promises).then(() => ({ updated: successfulUpdates })); - } - return new UpdateCommand(args, { namespace: this.namespace }).exec(this.client); - }; + ) => new UpdateCommand(args, { namespace: this.namespace }).exec(this.client); /** * It's used for retrieving specific items from the index namespace, optionally including diff --git a/src/http/index.ts b/src/http/index.ts index c448e80..97b2b46 100644 --- a/src/http/index.ts +++ b/src/http/index.ts @@ -28,22 +28,22 @@ export interface Requester { export type RetryConfig = | false | { - /** - * The number of retries to attempt before giving up. - * - * @default 5 - */ - retries?: number; - /** - * A backoff function receives the current retry cound and returns a number in milliseconds to wait before retrying. - * - * @default - * ```ts - * Math.exp(retryCount) * 50 - * ``` - */ - backoff?: (retryCount: number) => number; - }; + /** + * The number of retries to attempt before giving up. + * + * @default 5 + */ + retries?: number; + /** + * A backoff function receives the current retry cound and returns a number in milliseconds to wait before retrying. + * + * @default + * ```ts + * Math.exp(retryCount) * 50 + * ``` + */ + backoff?: (retryCount: number) => number; + }; export type RequesterConfig = { /** diff --git a/src/vector.ts b/src/vector.ts index cabc7e4..d91d6d9 100644 --- a/src/vector.ts +++ b/src/vector.ts @@ -134,21 +134,7 @@ export class Index { update = ( args: CommandArgs>, options?: { namespace?: string } - ) => { - if (Array.isArray(args)) { - let successfulUpdates = 0; - const promises = args.map((element) => { - const command = new UpdateCommand(element, options); - - return command.exec(this.client).then(() => { - successfulUpdates++; - }); - }); - - return Promise.all(promises).then(() => ({ updated: successfulUpdates })); - } - return new UpdateCommand(args, options).exec(this.client); - }; + ) => new UpdateCommand(args, options).exec(this.client); /** * It's used for retrieving specific items from the index, optionally including From 6aaa6b663748988f59520b7e218168ddd6707d30 Mon Sep 17 00:00:00 2001 From: fahreddinozcan Date: Wed, 22 May 2024 11:06:07 +0200 Subject: [PATCH 12/14] revert namespace reset test change --- src/commands/client/namespace/index.test.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/commands/client/namespace/index.test.ts b/src/commands/client/namespace/index.test.ts index dbd1e25..3301d50 100644 --- a/src/commands/client/namespace/index.test.ts +++ b/src/commands/client/namespace/index.test.ts @@ -56,7 +56,11 @@ describe("NAMESPACE", () => { await awaitUntilIndexed(index); - const res = await namespace.fetch([1], { includeMetadata: true }); + const res = await namespace.query({ + vector: range(0, 384), + topK: 3, + includeMetadata: true, + }); expect(res.length).toEqual(1); await namespace.reset(); From a86b85726993183cbef51d5d9e2c5eb26393baca Mon Sep 17 00:00:00 2001 From: fahreddinozcan Date: Wed, 22 May 2024 11:11:45 +0200 Subject: [PATCH 13/14] update jsdocs --- src/commands/client/namespace/index.ts | 2 +- src/vector.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/client/namespace/index.ts b/src/commands/client/namespace/index.ts index 136309d..f9be685 100644 --- a/src/commands/client/namespace/index.ts +++ b/src/commands/client/namespace/index.ts @@ -79,7 +79,7 @@ export class Namespace { * @param {number[]} args.vector - The feature vector associated with the item. * @param {Record} [args.metadata] - Optional metadata to be associated with the item. * - * @returns {string} A promise that resolves with the result of the update operation after the command is executed. + * @returns {Promise<{updated: number}>} A promise that resolves with the result of the update operation after the command is executed. */ update = ( args: CommandArgs> diff --git a/src/vector.ts b/src/vector.ts index d91d6d9..561e739 100644 --- a/src/vector.ts +++ b/src/vector.ts @@ -129,7 +129,7 @@ export class Index { * @param {Record} [args.metadata] - Optional metadata to be associated with the item. * @param {string} [args.namespace] - The namespace to update the item in. * - * @returns {string} A promise that resolves with the result of the update operation after the command is executed. + * @returns {Promise<{updated: number}>} A promise that resolves with the result of the update operation after the command is executed. */ update = ( args: CommandArgs>, From 0163cb3a22fdb311867eb946e2fde91998e83eb7 Mon Sep 17 00:00:00 2001 From: fahreddinozcan Date: Fri, 24 May 2024 09:54:06 +0200 Subject: [PATCH 14/14] address review --- src/commands/client/namespace/index.test.ts | 4 ++-- src/commands/client/namespace/index.ts | 5 ++--- src/vector.ts | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/commands/client/namespace/index.test.ts b/src/commands/client/namespace/index.test.ts index 3301d50..5c15b11 100644 --- a/src/commands/client/namespace/index.test.ts +++ b/src/commands/client/namespace/index.test.ts @@ -90,7 +90,7 @@ describe("NAMESPACE", () => { }, ]); - awaitUntilIndexed(index); + await awaitUntilIndexed(index); const res = await namespace.update({ id: "test-1", @@ -99,7 +99,7 @@ describe("NAMESPACE", () => { expect(res).toEqual({ updated: 1 }); - awaitUntilIndexed(index); + await awaitUntilIndexed(index); const fetchData = await namespace.fetch(["test-1"], { includeMetadata: true }); diff --git a/src/commands/client/namespace/index.ts b/src/commands/client/namespace/index.ts index f9be685..48bef9f 100644 --- a/src/commands/client/namespace/index.ts +++ b/src/commands/client/namespace/index.ts @@ -67,8 +67,7 @@ export class Namespace { * ```js * const updateArgs = { * id: '123', - * vector: [0.42, 0.87, ...], - * metadata: { property1: 'value1', property2: 'value2' } + * metadata: { updatedProperty: 'value1' } * }; * const updateResult = await index.update(updateArgs); * console.log(updateResult); // Outputs the result of the update operation @@ -79,7 +78,7 @@ export class Namespace { * @param {number[]} args.vector - The feature vector associated with the item. * @param {Record} [args.metadata] - Optional metadata to be associated with the item. * - * @returns {Promise<{updated: number}>} A promise that resolves with the result of the update operation after the command is executed. + * @returns {Promise<{updated: number}>} A promise that returns the number of items successfully updated. */ update = ( args: CommandArgs> diff --git a/src/vector.ts b/src/vector.ts index 561e739..7fd7e1f 100644 --- a/src/vector.ts +++ b/src/vector.ts @@ -129,7 +129,7 @@ export class Index { * @param {Record} [args.metadata] - Optional metadata to be associated with the item. * @param {string} [args.namespace] - The namespace to update the item in. * - * @returns {Promise<{updated: number}>} A promise that resolves with the result of the update operation after the command is executed. + * @returns {Promise<{updated: number}>} A promise that returns the number of items successfully updated. */ update = ( args: CommandArgs>,