From 69215698754e85256e7e3affec07a28ecc8523c8 Mon Sep 17 00:00:00 2001 From: CahidArda Date: Wed, 11 Sep 2024 14:44:07 +0300 Subject: [PATCH 1/3] feat: add reset all namespaces option --- src/commands/client/reset/index.test.ts | 69 ++++++++++++++++++++++++- src/commands/client/reset/index.ts | 9 +++- src/commands/command.ts | 4 +- src/vector.ts | 25 +++++++-- 4 files changed, 99 insertions(+), 8 deletions(-) diff --git a/src/commands/client/reset/index.test.ts b/src/commands/client/reset/index.test.ts index 7278c5d..c27788e 100644 --- a/src/commands/client/reset/index.test.ts +++ b/src/commands/client/reset/index.test.ts @@ -1,6 +1,6 @@ -import { describe, expect, test } from "bun:test"; +import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { FetchCommand, ResetCommand, UpsertCommand } from "@commands/index"; -import { awaitUntilIndexed, newHttpClient, randomID, range } from "@utils/test-utils"; +import { Index, awaitUntilIndexed, newHttpClient, randomID, range } from "@utils/test-utils"; const client = newHttpClient(); @@ -38,4 +38,69 @@ describe("RESET", () => { }, { timeout: 30000 } ); + + describe("reset options", () => { + const namespaces = ["ns-1", "ns-2"]; + const index = new Index({ + token: process.env.UPSTASH_VECTOR_REST_TOKEN!, + url: process.env.UPSTASH_VECTOR_REST_URL!, + }); + + const vectorCount = 5; + const vectorIds = new Array(vectorCount).fill("").map((_, index) => `vector-${index}`); + + beforeEach(async () => { + // insert vertors to the default namespace and to the two namespaces + await Promise.all( + [undefined, ...namespaces].map(async (ns) => { + const randomizedData = new Array(vectorCount) + .fill("") + .map((_, index) => ({ id: vectorIds[index], vector: range(0, 384) })); + + await new UpsertCommand(randomizedData, { namespace: ns }).exec(client); + await awaitUntilIndexed(client); + }) + ); + + const info = await index.info(); + expect(info.namespaces[""].vectorCount).toBe(vectorCount); + expect(info.namespaces[namespaces[0]].vectorCount).toBe(vectorCount); + expect(info.namespaces[namespaces[1]].vectorCount).toBe(vectorCount); + }); + + afterEach(async () => { + await index.reset({ all: true }); + + // make sure that index is empty + const info = await index.info(); + expect(info.vectorCount).toBe(0); + }); + + test("should reset default namespace", async () => { + await index.reset(); + const info = await index.info(); + + expect(info.namespaces[""].vectorCount).toBe(0); + expect(info.namespaces[namespaces[0]].vectorCount).toBe(vectorCount); + expect(info.namespaces[namespaces[1]].vectorCount).toBe(vectorCount); + }); + + test("should reset given namespace", async () => { + await index.reset({ namespace: namespaces[0] }); + const info = await index.info(); + + expect(info.namespaces[""].vectorCount).toBe(vectorCount); + expect(info.namespaces[namespaces[0]].vectorCount).toBe(0); + expect(info.namespaces[namespaces[1]].vectorCount).toBe(vectorCount); + }); + + test("should reset all namespaces", async () => { + await index.reset({ all: true }); + const info = await index.info(); + + expect(info.namespaces[""].vectorCount).toBe(0); + expect(info.namespaces[namespaces[0]].vectorCount).toBe(0); + expect(info.namespaces[namespaces[1]].vectorCount).toBe(0); + }); + }); }); diff --git a/src/commands/client/reset/index.ts b/src/commands/client/reset/index.ts index 18377ab..25ad1d7 100644 --- a/src/commands/client/reset/index.ts +++ b/src/commands/client/reset/index.ts @@ -1,16 +1,21 @@ import type { NAMESPACE } from "@commands/client/types"; import { Command } from "@commands/command"; -type ResetEndpointVariants = `reset` | `reset/${NAMESPACE}`; +type ResetEndpointVariants = `reset` | `reset/${NAMESPACE}` | `reset?all`; -type ResetCommandOptions = { namespace?: string }; +export type ResetCommandOptions = + | { namespace?: string; all?: never } + | { namespace?: never; all?: true }; export class ResetCommand extends Command { constructor(options?: ResetCommandOptions) { let endpoint: ResetEndpointVariants = "reset"; if (options?.namespace) { endpoint = `${endpoint}/${options.namespace}`; + } else if (options?.all) { + endpoint = `${endpoint}?all`; } + super([], endpoint); } } diff --git a/src/commands/command.ts b/src/commands/command.ts index 5b1ddbd..0b153e8 100644 --- a/src/commands/command.ts +++ b/src/commands/command.ts @@ -20,7 +20,9 @@ const ENDPOINTS = [ export type EndpointVariants = | (typeof ENDPOINTS)[number] - | `${(typeof ENDPOINTS)[number]}/${NAMESPACE}`; + | `${(typeof ENDPOINTS)[number]}/${NAMESPACE}` + | `reset?all`; // here to make sure that reset?all/ is invalid + /** * TResult is the raw data returned from upstash, which may need to be transformed or parsed. */ diff --git a/src/vector.ts b/src/vector.ts index 4b924d8..1c8ca13 100644 --- a/src/vector.ts +++ b/src/vector.ts @@ -7,6 +7,7 @@ import { QueryManyCommand, RangeCommand, ResetCommand, + ResetCommandOptions, UpdateCommand, UpsertCommand, } from "@commands/client"; @@ -201,17 +202,35 @@ export class Index { new FetchCommand(args).exec(this.client); /** - * It's used for wiping an entire index. + * It's used for wiping the index. + * + * By default, resets the default namespace: * * @example * ```js * await index.reset(); - * console.log('Index has been reset'); + * console.log('Default namespace has been reset'); + * ``` + * + * To reset a namespace, call reset like: + * + * @example + * ```js + * await index.reset({ namespace: "ns" }); + * console.log('Namespace ns has been reset'); + * ``` + * + * If you want to reset all namespaces, call reset like: + * + * @example + * ```js + * await index.reset({ all: true }); + * console.log('All namespaces have been reset'); * ``` * * @returns {Promise} A promise that resolves with the result of the reset operation after the command is executed. */ - reset = (options?: { namespace?: string }) => new ResetCommand(options).exec(this.client); + reset = (options?: ResetCommandOptions) => new ResetCommand(options).exec(this.client); /** * Retrieves a range of items from the index. From 6eb9e58ff3716e19afb1a4c92f21cb9435ff5838 Mon Sep 17 00:00:00 2001 From: CahidArda Date: Thu, 12 Sep 2024 10:43:22 +0300 Subject: [PATCH 2/3] fix: add namespace example to range command --- src/vector.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/vector.ts b/src/vector.ts index 1c8ca13..87c234e 100644 --- a/src/vector.ts +++ b/src/vector.ts @@ -246,6 +246,12 @@ export class Index { * const rangeResults = await index.range(rangeArgs); * console.log(rangeResults); // Outputs the result of the range operation * ``` + * + * You can also pass a namespace like: + * + * ```js + * const rangeResults = await index.range(rangeArgs, { namespace: "ns" }); + * ``` * * @param {CommandArgs} args - The arguments for the range command. * @param {number|string} args.cursor - The starting point (cursor) for the range query. From 2c4cd20403efa867b24a200186b4b9f5d8a7ab3c Mon Sep 17 00:00:00 2001 From: CahidArda Date: Thu, 12 Sep 2024 10:43:27 +0300 Subject: [PATCH 3/3] fix: add namespace example to range command --- src/vector.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vector.ts b/src/vector.ts index 87c234e..9562d7b 100644 --- a/src/vector.ts +++ b/src/vector.ts @@ -246,9 +246,9 @@ export class Index { * const rangeResults = await index.range(rangeArgs); * console.log(rangeResults); // Outputs the result of the range operation * ``` - * + * * You can also pass a namespace like: - * + * * ```js * const rangeResults = await index.range(rangeArgs, { namespace: "ns" }); * ```