Skip to content

Commit afde113

Browse files
committed
address PR comments
1 parent d86bd88 commit afde113

File tree

7 files changed

+72
-67
lines changed

7 files changed

+72
-67
lines changed

src/common/config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ export interface UserConfig extends CliOptions {
183183
maxBytesPerQuery: number;
184184
atlasTemporaryDatabaseUserLifetimeMs: number;
185185
voyageApiKey: string;
186+
vectorSearchDimensions: number;
187+
vectorSearchSimilarityFunction: "cosine" | "euclidean" | "dotProduct";
186188
}
187189

188190
export const defaultUserConfig: UserConfig = {
@@ -214,6 +216,8 @@ export const defaultUserConfig: UserConfig = {
214216
maxBytesPerQuery: 16 * 1024 * 1024, // By default, we only return ~16 mb of data per query / aggregation
215217
atlasTemporaryDatabaseUserLifetimeMs: 4 * 60 * 60 * 1000, // 4 hours
216218
voyageApiKey: "",
219+
vectorSearchDimensions: 1024,
220+
vectorSearchSimilarityFunction: "euclidean",
217221
};
218222

219223
export const config = setupUserConfig({

src/common/connectionManager.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ export class ConnectionStateConnected implements ConnectionState {
4646
public async isSearchSupported(): Promise<boolean> {
4747
if (this._isSearchSupported === undefined) {
4848
try {
49-
const dummyDatabase = `search-index-test-db-${Date.now()}`;
50-
const dummyCollection = `search-index-test-coll-${Date.now()}`;
49+
const dummyDatabase = "test";
50+
const dummyCollection = "test";
5151
// If a cluster supports search indexes, the call below will succeed
5252
// with a cursor otherwise will throw an Error
5353
await this.serviceProvider.getSearchIndexes(dummyDatabase, dummyCollection);

src/common/session.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ export class Session extends EventEmitter<SessionEvents> {
141141
return this.connectionManager.currentConnectionState.tag === "connected";
142142
}
143143

144-
get isConnectedToMongot(): Promise<boolean> {
144+
isSearchSupported(): Promise<boolean> {
145145
const state = this.connectionManager.currentConnectionState;
146146
if (state.tag === "connected") {
147147
return state.isSearchSupported();

src/resources/common/debug.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export class DebugResource extends ReactiveResource<
6161

6262
switch (this.current.tag) {
6363
case "connected": {
64-
const searchIndexesSupported = await this.session.isConnectedToMongot;
64+
const searchIndexesSupported = await this.session.isSearchSupported();
6565
result += `The user is connected to the MongoDB cluster${searchIndexesSupported ? " with support for search indexes" : " without any support for search indexes"}.`;
6666
break;
6767
}

src/tools/mongodb/create/createIndex.ts

Lines changed: 61 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -5,65 +5,66 @@ import type { ToolCategory } from "../../tool.js";
55
import { type ToolArgs, type OperationType, FeatureFlags } from "../../tool.js";
66
import type { IndexDirection } from "mongodb";
77

8-
const vectorSearchIndexDefinition = z.object({
9-
type: z.literal("vectorSearch"),
10-
fields: z
11-
.array(
12-
z.discriminatedUnion("type", [
13-
z
14-
.object({
15-
type: z.literal("filter"),
16-
path: z
17-
.string()
18-
.describe(
19-
"Name of the field to index. For nested fields, use dot notation to specify path to embedded fields"
20-
),
21-
})
22-
.strict()
23-
.describe("Definition for a field that will be used for pre-filtering results."),
24-
z
25-
.object({
26-
type: z.literal("vector"),
27-
path: z
28-
.string()
29-
.describe(
30-
"Name of the field to index. For nested fields, use dot notation to specify path to embedded fields"
31-
),
32-
numDimensions: z
33-
.number()
34-
.min(1)
35-
.max(8192)
36-
.describe(
37-
"Number of vector dimensions that MongoDB Vector Search enforces at index-time and query-time"
38-
),
39-
similarity: z
40-
.enum(["cosine", "euclidean", "dotProduct"])
41-
.default("cosine")
42-
.describe(
43-
"Vector similarity function to use to search for top K-nearest neighbors. You can set this field only for vector-type fields."
44-
),
45-
quantization: z
46-
.enum(["none", "scalar", "binary"])
47-
.optional()
48-
.default("none")
49-
.describe(
50-
"Type of automatic vector quantization for your vectors. Use this setting only if your embeddings are float or double vectors."
51-
),
52-
})
53-
.strict()
54-
.describe("Definition for a field that contains vector embeddings."),
55-
])
56-
)
57-
.nonempty()
58-
.refine((fields) => fields.some((f) => f.type === "vector"), {
59-
message: "At least one vector field must be defined",
60-
})
61-
.describe(
62-
"Definitions for the vector and filter fields to index, one definition per document. You must specify `vector` for fields that contain vector embeddings and `filter` for additional fields to filter on. At least one vector-type field definition is required."
63-
),
64-
});
65-
668
export class CreateIndexTool extends MongoDBToolBase {
9+
private vectorSearchIndexDefinition = z.object({
10+
type: z.literal("vectorSearch"),
11+
fields: z
12+
.array(
13+
z.discriminatedUnion("type", [
14+
z
15+
.object({
16+
type: z.literal("filter"),
17+
path: z
18+
.string()
19+
.describe(
20+
"Name of the field to index. For nested fields, use dot notation to specify path to embedded fields"
21+
),
22+
})
23+
.strict()
24+
.describe("Definition for a field that will be used for pre-filtering results."),
25+
z
26+
.object({
27+
type: z.literal("vector"),
28+
path: z
29+
.string()
30+
.describe(
31+
"Name of the field to index. For nested fields, use dot notation to specify path to embedded fields"
32+
),
33+
numDimensions: z
34+
.number()
35+
.min(1)
36+
.max(8192)
37+
.default(this.config.vectorSearchDimensions)
38+
.describe(
39+
"Number of vector dimensions that MongoDB Vector Search enforces at index-time and query-time"
40+
),
41+
similarity: z
42+
.enum(["cosine", "euclidean", "dotProduct"])
43+
.default(this.config.vectorSearchSimilarityFunction)
44+
.describe(
45+
"Vector similarity function to use to search for top K-nearest neighbors. You can set this field only for vector-type fields."
46+
),
47+
quantization: z
48+
.enum(["none", "scalar", "binary"])
49+
.optional()
50+
.default("none")
51+
.describe(
52+
"Type of automatic vector quantization for your vectors. Use this setting only if your embeddings are float or double vectors."
53+
),
54+
})
55+
.strict()
56+
.describe("Definition for a field that contains vector embeddings."),
57+
])
58+
)
59+
.nonempty()
60+
.refine((fields) => fields.some((f) => f.type === "vector"), {
61+
message: "At least one vector field must be defined",
62+
})
63+
.describe(
64+
"Definitions for the vector and filter fields to index, one definition per document. You must specify `vector` for fields that contain vector embeddings and `filter` for additional fields to filter on. At least one vector-type field definition is required."
65+
),
66+
});
67+
6768
public name = "create-index";
6869
protected description = "Create an index for a collection";
6970
protected argsShape = {
@@ -76,7 +77,7 @@ export class CreateIndexTool extends MongoDBToolBase {
7677
type: z.literal("classic"),
7778
keys: z.object({}).catchall(z.custom<IndexDirection>()).describe("The index definition"),
7879
}),
79-
...(this.isFeatureFlagEnabled(FeatureFlags.VectorSearch) ? [vectorSearchIndexDefinition] : []),
80+
...(this.isFeatureFlagEnabled(FeatureFlags.VectorSearch) ? [this.vectorSearchIndexDefinition] : []),
8081
])
8182
)
8283
.describe(
@@ -110,7 +111,7 @@ export class CreateIndexTool extends MongoDBToolBase {
110111
break;
111112
case "vectorSearch":
112113
{
113-
const isVectorSearchSupported = await this.session.isConnectedToMongot;
114+
const isVectorSearchSupported = await this.session.isSearchSupported();
114115
if (!isVectorSearchSupported) {
115116
// TODO: remove hacky casts once we merge the local dev tools
116117
const isLocalAtlasAvailable =

tests/unit/common/session.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,15 +134,15 @@ describe("Session", () => {
134134
await session.connectToMongoDB({
135135
connectionString: "mongodb://localhost:27017",
136136
});
137-
expect(await session.isConnectedToMongot).toEqual(true);
137+
expect(await session.isSearchSupported()).toEqual(true);
138138
});
139139

140140
it("should return false if listing search indexes fail with search error", async () => {
141141
getSearchIndexesMock.mockRejectedValue(new Error("SearchNotEnabled"));
142142
await session.connectToMongoDB({
143143
connectionString: "mongodb://localhost:27017",
144144
});
145-
expect(await session.isConnectedToMongot).toEqual(false);
145+
expect(await session.isSearchSupported()).toEqual(false);
146146
});
147147
});
148148
});

tests/unit/resources/common/debug.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ describe("debug resource", () => {
103103
});
104104

105105
it("should notify if a cluster supports search indexes", async () => {
106-
vi.spyOn(session, "isConnectedToMongot", "get").mockImplementation(() => Promise.resolve(true));
106+
vi.spyOn(session, "isSearchSupported").mockImplementation(() => Promise.resolve(true));
107107
debugResource.reduceApply("connect", undefined);
108108
const output = await debugResource.toOutput();
109109

0 commit comments

Comments
 (0)