-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #36 from upstash/DX-1015
Dx 1015
- Loading branch information
Showing
8 changed files
with
261 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,2 @@ | ||
import type { NAMESPACE } from "@commands/client/types"; | ||
import { Dict } from "@commands/client/types"; | ||
import { Command } from "@commands/command"; | ||
|
||
type QueryCommandPayload = { | ||
topK: number; | ||
filter?: string; | ||
includeVectors?: boolean; | ||
includeMetadata?: boolean; | ||
includeData?: boolean; | ||
} & ({ vector: number[]; data?: never } | { data: string; vector?: never }); | ||
|
||
export type QueryResult<TMetadata = Dict> = { | ||
id: number | string; | ||
score: number; | ||
vector?: number[]; | ||
metadata?: TMetadata; | ||
data?: string; | ||
}; | ||
|
||
type QueryCommandOptions = { namespace?: string }; | ||
|
||
type QueryEndpointVariants = | ||
| `query` | ||
| `query-data` | ||
| `query/${NAMESPACE}` | ||
| `query-data/${NAMESPACE}`; | ||
|
||
export class QueryCommand<TMetadata> extends Command<QueryResult<TMetadata>[]> { | ||
constructor(payload: QueryCommandPayload, options?: QueryCommandOptions) { | ||
let endpoint: QueryEndpointVariants = "query"; | ||
|
||
if ("data" in payload) { | ||
endpoint = "query-data"; | ||
} | ||
|
||
if (options?.namespace) { | ||
endpoint = `${endpoint}/${options.namespace}`; | ||
} | ||
|
||
super(payload, endpoint); | ||
} | ||
} | ||
export * from "./query-many"; | ||
export * from "./query-single"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
import { afterAll, describe, expect, test } from "bun:test"; | ||
import { UpsertCommand } from "@commands/client/upsert"; | ||
import { Index, awaitUntilIndexed, newHttpClient, randomID, range } from "@utils/test-utils"; | ||
import { QueryManyCommand } from "."; | ||
|
||
const client = newHttpClient(); | ||
|
||
describe("QUERY", () => { | ||
const index = new Index(); | ||
|
||
afterAll(async () => { | ||
await index.reset(); | ||
}); | ||
test("should query in batches successfully", async () => { | ||
const ID = randomID(); | ||
const initialData = [ | ||
{ | ||
id: `1-${ID}`, | ||
vector: range(0, 384), | ||
metadata: { | ||
animal: "elephant", | ||
tags: ["mammal"], | ||
diet: "herbivore", | ||
}, | ||
}, | ||
{ | ||
id: `2-${ID}`, | ||
vector: range(0, 384), | ||
metadata: { | ||
animal: "tiger", | ||
tags: ["mammal"], | ||
diet: "carnivore", | ||
}, | ||
}, | ||
]; | ||
await new UpsertCommand(initialData).exec(client); | ||
|
||
await awaitUntilIndexed(client); | ||
|
||
const res = await new QueryManyCommand<{ | ||
animal: string; | ||
tags: string[]; | ||
diet: string; | ||
}>([ | ||
{ | ||
vector: initialData[0].vector, | ||
topK: 1, | ||
filter: "tags[0] = 'mammal' AND diet = 'herbivore'", | ||
includeMetadata: true, | ||
}, | ||
{ | ||
vector: initialData[1].vector, | ||
topK: 1, | ||
filter: "tags[0] = 'mammal' AND diet = 'carnivore'", | ||
includeMetadata: true, | ||
}, | ||
]).exec(client); | ||
|
||
expect(res).toEqual([ | ||
[ | ||
{ | ||
id: `1-${ID}`, | ||
score: 1, | ||
metadata: { animal: "elephant", tags: ["mammal"], diet: "herbivore" }, | ||
}, | ||
], | ||
[ | ||
{ | ||
id: `2-${ID}`, | ||
score: 1, | ||
metadata: { animal: "tiger", tags: ["mammal"], diet: "carnivore" }, | ||
}, | ||
], | ||
]); | ||
}); | ||
}); | ||
|
||
describe("QUERY with Index Client", () => { | ||
const index = new Index(); | ||
|
||
afterAll(async () => { | ||
await index.reset(); | ||
}); | ||
test("should query in batches successfully", async () => { | ||
const ID = randomID(); | ||
const initialData = [ | ||
{ | ||
id: `1-${ID}`, | ||
vector: range(0, 384), | ||
metadata: { | ||
animal: "elephant", | ||
tags: ["mammal"], | ||
diet: "herbivore", | ||
}, | ||
}, | ||
{ | ||
id: `2-${ID}`, | ||
vector: range(0, 384), | ||
metadata: { | ||
animal: "tiger", | ||
tags: ["mammal"], | ||
diet: "carnivore", | ||
}, | ||
}, | ||
]; | ||
|
||
await index.upsert(initialData); | ||
|
||
await awaitUntilIndexed(index); | ||
|
||
const res = await index.queryMany<{ | ||
animal: string; | ||
tags: string[]; | ||
diet: string; | ||
}>([ | ||
{ | ||
vector: initialData[0].vector, | ||
topK: 1, | ||
filter: "tags[0] = 'mammal' AND diet = 'herbivore'", | ||
includeMetadata: true, | ||
}, | ||
{ | ||
vector: initialData[1].vector, | ||
topK: 1, | ||
filter: "tags[0] = 'mammal' AND diet = 'carnivore'", | ||
includeMetadata: true, | ||
}, | ||
]); | ||
|
||
expect(res).toEqual([ | ||
[ | ||
{ | ||
id: `1-${ID}`, | ||
score: 1, | ||
metadata: { animal: "elephant", tags: ["mammal"], diet: "herbivore" }, | ||
}, | ||
], | ||
[ | ||
{ | ||
id: `2-${ID}`, | ||
score: 1, | ||
metadata: { animal: "tiger", tags: ["mammal"], diet: "carnivore" }, | ||
}, | ||
], | ||
]); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { Command } from "@commands/command"; | ||
import { | ||
QueryCommandOptions, | ||
QueryCommandPayload, | ||
QueryEndpointVariants, | ||
QueryResult, | ||
} from "../types"; | ||
|
||
export class QueryManyCommand<TMetadata> extends Command<QueryResult<TMetadata>[][]> { | ||
constructor(payload: QueryCommandPayload[], options?: QueryCommandOptions) { | ||
let endpoint: QueryEndpointVariants = "query"; | ||
|
||
const hasData = payload.some((p) => p.data); | ||
endpoint = hasData ? "query-data" : "query"; | ||
|
||
if (options?.namespace) { | ||
endpoint = `${endpoint}/${options.namespace}`; | ||
} | ||
|
||
super(payload, endpoint); | ||
} | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { Command } from "@commands/command"; | ||
import { | ||
QueryCommandOptions, | ||
QueryCommandPayload, | ||
QueryEndpointVariants, | ||
QueryResult, | ||
} from "../types"; | ||
|
||
export class QueryCommand<TMetadata> extends Command<QueryResult<TMetadata>[]> { | ||
constructor(payload: QueryCommandPayload, options?: QueryCommandOptions) { | ||
let endpoint: QueryEndpointVariants = "query"; | ||
|
||
if ("data" in payload) { | ||
endpoint = "query-data"; | ||
} | ||
|
||
if (options?.namespace) { | ||
endpoint = `${endpoint}/${options.namespace}`; | ||
} | ||
|
||
super(payload, endpoint); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { Dict, NAMESPACE } from "../types"; | ||
|
||
export type QueryCommandPayload = { | ||
topK: number; | ||
filter?: string; | ||
includeVectors?: boolean; | ||
includeMetadata?: boolean; | ||
includeData?: boolean; | ||
} & ({ vector: number[]; data?: never } | { data: string; vector?: never }); | ||
|
||
export type QueryResult<TMetadata = Dict> = { | ||
id: number | string; | ||
score: number; | ||
vector?: number[]; | ||
metadata?: TMetadata; | ||
data?: string; | ||
}; | ||
|
||
export type QueryCommandOptions = { namespace?: string }; | ||
|
||
export type QueryEndpointVariants = | ||
| `query` | ||
| `query-data` | ||
| `query/${NAMESPACE}` | ||
| `query-data/${NAMESPACE}`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
export { type Vector } from "./client/types"; | ||
export { type RangeResult } from "./client/range/index"; | ||
export { type FetchResult } from "./client/fetch/index"; | ||
export { type QueryResult } from "./client/query/index"; | ||
export { type QueryResult } from "./client/query/types"; | ||
export { type InfoResult } from "./client/info/index"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters