Skip to content

Commit bd0c2ad

Browse files
fix(shell-api): create vector search index with description options MONGOSH-1851 (#2377)
* fix(shell-api): create vector search index with description options MONGOSH-1851 * refactor: use overloads * fix: remove unsupported use cases * docs: fix comment
1 parent 30ec9a9 commit bd0c2ad

File tree

5 files changed

+90
-63
lines changed

5 files changed

+90
-63
lines changed

packages/service-provider-core/src/all-transport-types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export type {
5757
ReplaceOptions,
5858
ResumeToken,
5959
RunCommandOptions,
60+
SearchIndexDescription,
6061
ServerSessionId,
6162
TagSet,
6263
TransactionOptions,

packages/service-provider-core/src/writable.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import type {
2424
DbOptions,
2525
OrderedBulkOperation,
2626
UnorderedBulkOperation,
27+
SearchIndexDescription,
2728
} from './all-transport-types';
2829
import type { ServiceProviderRunCommandCursor } from './cursors';
2930

@@ -312,7 +313,7 @@ export default interface Writable {
312313
*
313314
* @param {String} database - The db name.
314315
* @param {String} collection - The collection name.
315-
* @param {Object[]} indexSpecs the spec of the indexes to be created.
316+
* @param {Object[]} indexSpecs - The spec of the indexes to be created.
316317
* @param {Object} options - The command options.
317318
* @param {DbOptions} dbOptions - The database options
318319
* @return {Promise}
@@ -385,12 +386,7 @@ export default interface Writable {
385386
createSearchIndexes(
386387
database: string,
387388
collection: string,
388-
// TODO(MONGOSH-1471): use SearchIndexDescription[] once available
389-
specs: {
390-
name: string;
391-
type?: 'search' | 'vectorSearch';
392-
definition: Document;
393-
}[],
389+
descriptions: SearchIndexDescription[],
394390
dbOptions?: DbOptions
395391
): Promise<string[]>;
396392

packages/shell-api/src/collection.spec.ts

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2633,31 +2633,7 @@ describe('Collection', function () {
26332633
serviceProvider.createSearchIndexes.resolves(['index_1']);
26342634
});
26352635

2636-
context('without anything', function () {
2637-
it('calls serviceProvider.createIndexes', async function () {
2638-
await collection.createSearchIndex();
2639-
2640-
expect(serviceProvider.createSearchIndexes).to.have.been.calledWith(
2641-
'db1',
2642-
'coll1',
2643-
[{ name: 'default', definition: {} }]
2644-
);
2645-
});
2646-
});
2647-
2648-
context('with name', function () {
2649-
it('calls serviceProvider.createIndexes', async function () {
2650-
await collection.createSearchIndex('my-index');
2651-
2652-
expect(serviceProvider.createSearchIndexes).to.have.been.calledWith(
2653-
'db1',
2654-
'coll1',
2655-
[{ name: 'my-index', definition: {} }]
2656-
);
2657-
});
2658-
});
2659-
2660-
context('with options', function () {
2636+
context('with definition options', function () {
26612637
it('calls serviceProvider.createIndexes', async function () {
26622638
await collection.createSearchIndex({ mappings: { dynamic: true } });
26632639

@@ -2669,7 +2645,7 @@ describe('Collection', function () {
26692645
});
26702646
});
26712647

2672-
context('with name, options', function () {
2648+
context('with name, definition options', function () {
26732649
it('calls serviceProvider.createIndexes', async function () {
26742650
await collection.createSearchIndex('my-index', {
26752651
mappings: { dynamic: true },
@@ -2683,7 +2659,7 @@ describe('Collection', function () {
26832659
});
26842660
});
26852661

2686-
context('with name, options and type !== search', function () {
2662+
context('with name, definition options and type !== search', function () {
26872663
it('calls serviceProvider.createSearchIndexes', async function () {
26882664
await collection.createSearchIndex('my-index', 'vectorSearch', {
26892665
mappings: { dynamic: true },
@@ -2703,7 +2679,7 @@ describe('Collection', function () {
27032679
});
27042680
});
27052681

2706-
context('with name, options and type === search', function () {
2682+
context('with name, definition options and type === search', function () {
27072683
it('calls serviceProvider.createSearchIndexes', async function () {
27082684
await collection.createSearchIndex('my-index', 'search', {
27092685
mappings: { dynamic: true },
@@ -2717,7 +2693,7 @@ describe('Collection', function () {
27172693
});
27182694
});
27192695

2720-
context('with options and type but no name', function () {
2696+
context('with definition options and type but no name', function () {
27212697
it('calls serviceProvider.createSearchIndexes', async function () {
27222698
await collection.createSearchIndex(
27232699
{ mappings: { dynamic: true } },
@@ -2737,6 +2713,30 @@ describe('Collection', function () {
27372713
);
27382714
});
27392715
});
2716+
2717+
context('with description options', function () {
2718+
it('calls serviceProvider.createSearchIndexes', async function () {
2719+
await collection.createSearchIndex({
2720+
name: 'my-index',
2721+
type: 'vectorSearch',
2722+
definition: {
2723+
mappings: { dynamic: true },
2724+
},
2725+
});
2726+
2727+
expect(serviceProvider.createSearchIndexes).to.have.been.calledWith(
2728+
'db1',
2729+
'coll1',
2730+
[
2731+
{
2732+
name: 'my-index',
2733+
type: 'vectorSearch',
2734+
definition: { mappings: { dynamic: true } },
2735+
},
2736+
]
2737+
);
2738+
});
2739+
});
27402740
});
27412741

27422742
describe('createSearchIndexes', function () {

packages/shell-api/src/collection.ts

Lines changed: 55 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import type {
2222
FindAndModifyMethodShellOptions,
2323
RemoveShellOptions,
2424
MapReduceShellOptions,
25+
SearchIndexDefinition,
2526
} from './helpers';
2627
import {
2728
adaptAggregateOptions,
@@ -67,6 +68,7 @@ import type {
6768
DropCollectionOptions,
6869
CheckMetadataConsistencyOptions,
6970
AggregateOptions,
71+
SearchIndexDescription,
7072
} from '@mongosh/service-provider-core';
7173
import type { RunCommandCursor, Database } from './index';
7274
import {
@@ -2383,51 +2385,77 @@ export default class Collection extends ShellApiWithMongoClass {
23832385
);
23842386
}
23852387

2388+
async createSearchIndex(
2389+
name: string,
2390+
definition: SearchIndexDefinition
2391+
): Promise<string>;
2392+
async createSearchIndex(
2393+
name: string,
2394+
type: 'search' | 'vectorSearch',
2395+
definition: SearchIndexDefinition
2396+
): Promise<string>;
2397+
async createSearchIndex(
2398+
definition: SearchIndexDefinition,
2399+
type?: 'search' | 'vectorSearch'
2400+
): Promise<string>;
2401+
async createSearchIndex(description: SearchIndexDescription): Promise<string>;
23862402
@serverVersions(['6.0.0', ServerVersions.latest])
23872403
@returnsPromise
23882404
@apiVersions([])
2389-
// TODO(MONGOSH-1471): use SearchIndexDescription once available
23902405
async createSearchIndex(
2391-
indexName?: string | Document,
2392-
type?: 'search' | 'vectorSearch' | Document,
2393-
definition?: Document
2406+
nameOrOptions?: string | SearchIndexDescription | SearchIndexDefinition,
2407+
typeOrOptions?: 'search' | 'vectorSearch' | SearchIndexDefinition,
2408+
definition?: SearchIndexDefinition
23942409
): Promise<string> {
2395-
if (typeof type === 'object' && type !== null) {
2396-
definition = type;
2397-
type = undefined;
2398-
}
2399-
if (typeof indexName === 'object' && indexName !== null) {
2400-
definition = indexName;
2401-
indexName = undefined;
2410+
let indexDescription: SearchIndexDescription;
2411+
2412+
if (
2413+
typeof nameOrOptions === 'object' &&
2414+
nameOrOptions !== null &&
2415+
nameOrOptions.definition
2416+
) {
2417+
indexDescription = nameOrOptions as SearchIndexDescription;
2418+
} else {
2419+
let indexName: string | undefined;
2420+
let indexType: 'search' | 'vectorSearch' | undefined;
2421+
2422+
if (typeof typeOrOptions === 'object' && typeOrOptions !== null) {
2423+
definition = typeOrOptions;
2424+
} else {
2425+
indexType = typeOrOptions;
2426+
}
2427+
2428+
if (typeof nameOrOptions === 'object' && nameOrOptions !== null) {
2429+
definition = nameOrOptions;
2430+
} else {
2431+
indexName = nameOrOptions;
2432+
}
2433+
2434+
indexDescription = {
2435+
name: indexName ?? 'default',
2436+
// Omitting type when it is 'search' for compat with older servers
2437+
...(indexType &&
2438+
indexType !== 'search' && {
2439+
type: indexType as 'search' | 'vectorSearch',
2440+
}),
2441+
definition: { ...definition },
2442+
};
24022443
}
24032444

2404-
this._emitCollectionApiCall('createSearchIndex', { indexName, definition });
2445+
this._emitCollectionApiCall('createSearchIndex', indexDescription);
24052446
const results = await this._mongo._serviceProvider.createSearchIndexes(
24062447
this._database._name,
24072448
this._name,
2408-
[
2409-
{
2410-
name: indexName ?? 'default',
2411-
// Omitting type when it is 'search' for compat with older servers
2412-
...(type &&
2413-
type !== 'search' && { type: type as 'search' | 'vectorSearch' }),
2414-
definition: { ...definition },
2415-
},
2416-
]
2449+
[indexDescription]
24172450
);
24182451
return results[0];
24192452
}
24202453

24212454
@serverVersions(['6.0.0', ServerVersions.latest])
24222455
@returnsPromise
24232456
@apiVersions([])
2424-
// TODO(MONGOSH-1471): use SearchIndexDescription once available
24252457
async createSearchIndexes(
2426-
specs: {
2427-
name: string;
2428-
type?: 'search' | 'vectorSearch';
2429-
definition: Document;
2430-
}[]
2458+
specs: SearchIndexDescription[]
24312459
): Promise<string[]> {
24322460
this._emitCollectionApiCall('createSearchIndexes', { specs });
24332461
return await this._mongo._serviceProvider.createSearchIndexes(

packages/shell-api/src/helpers.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,3 +1295,5 @@ export function buildConfigChunksCollectionMatch(
12951295
export const aggregateBackgroundOptionNotSupportedHelp =
12961296
'the background option is not supported by the aggregate method and will be ignored, ' +
12971297
'use runCommand to use { background: true } with Atlas Data Federation';
1298+
1299+
export type SearchIndexDefinition = Document;

0 commit comments

Comments
 (0)