From ef0391db3f2f37610ecc16f6d67953d60929ace1 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Mon, 27 Nov 2023 22:44:33 +0100 Subject: [PATCH 1/2] feat(shell-api): support `type` field for search index creation MONGOSH-1631 Now that SERVER-83107 is complete, we can add this to mongosh. --- .../service-provider-core/src/writable.ts | 6 +- .../src/cli-service-provider.ts | 6 +- packages/shell-api/src/collection.spec.ts | 59 +++++++++++++++++++ packages/shell-api/src/collection.ts | 20 ++++++- 4 files changed, 87 insertions(+), 4 deletions(-) diff --git a/packages/service-provider-core/src/writable.ts b/packages/service-provider-core/src/writable.ts index 874a01241..3a82dceeb 100644 --- a/packages/service-provider-core/src/writable.ts +++ b/packages/service-provider-core/src/writable.ts @@ -385,7 +385,11 @@ export default interface Writable { database: string, collection: string, // TODO(MONGOSH-1471): use SearchIndexDescription[] once available - specs: { name: string; definition: Document }[], + specs: { + name: string; + type?: 'search' | 'vectorSearch'; + definition: Document; + }[], dbOptions?: DbOptions ): Promise; diff --git a/packages/service-provider-server/src/cli-service-provider.ts b/packages/service-provider-server/src/cli-service-provider.ts index 0af34da7d..88bd6ba77 100644 --- a/packages/service-provider-server/src/cli-service-provider.ts +++ b/packages/service-provider-server/src/cli-service-provider.ts @@ -1470,7 +1470,11 @@ class CliServiceProvider database: string, collection: string, // TODO(MONGOSH-1471): use SearchIndexDescription[] once available - specs: { name: string; definition: Document }[], + specs: { + name: string; + type?: 'search' | 'vectorSearch'; + definition: Document; + }[], dbOptions?: DbOptions ): Promise { return this.db(database, dbOptions) diff --git a/packages/shell-api/src/collection.spec.ts b/packages/shell-api/src/collection.spec.ts index 810d19e50..7cb2ede63 100644 --- a/packages/shell-api/src/collection.spec.ts +++ b/packages/shell-api/src/collection.spec.ts @@ -2584,6 +2584,61 @@ describe('Collection', function () { ); }); }); + + context('with name, options and type !== search', function () { + it('calls serviceProvider.createIndexes', async function () { + await collection.createSearchIndex('my-index', 'vectorSearch', { + mappings: { dynamic: true }, + }); + + expect(serviceProvider.createSearchIndexes).to.have.been.calledWith( + 'db1', + 'coll1', + [ + { + name: 'my-index', + type: 'vectorSearch', + definition: { mappings: { dynamic: true } }, + }, + ] + ); + }); + }); + + context('with name, options and type === search', function () { + it('calls serviceProvider.createIndexes', async function () { + await collection.createSearchIndex('my-index', 'search', { + mappings: { dynamic: true }, + }); + + expect(serviceProvider.createSearchIndexes).to.have.been.calledWith( + 'db1', + 'coll1', + [{ name: 'my-index', definition: { mappings: { dynamic: true } } }] + ); + }); + }); + + context('with options and type but no name', function () { + it('calls serviceProvider.createIndexes', async function () { + await collection.createSearchIndex( + { mappings: { dynamic: true } }, + 'vectorSearch' + ); + + expect(serviceProvider.createSearchIndexes).to.have.been.calledWith( + 'db1', + 'coll1', + [ + { + name: 'default', + type: 'vectorSearch', + definition: { mappings: { dynamic: true } }, + }, + ] + ); + }); + }); }); describe('createSearchIndexes', function () { @@ -2595,6 +2650,8 @@ describe('Collection', function () { await collection.createSearchIndexes([ { name: 'foo', definition: { mappings: { dynamic: true } } }, { name: 'bar', definition: {} }, + { name: 'sch', type: 'search', definition: {} }, + { name: 'vec', type: 'vectorSearch', definition: {} }, ]); expect(serviceProvider.createSearchIndexes).to.have.been.calledWith( @@ -2603,6 +2660,8 @@ describe('Collection', function () { [ { name: 'foo', definition: { mappings: { dynamic: true } } }, { name: 'bar', definition: {} }, + { name: 'sch', definition: {} }, + { name: 'vec', type: 'vectorSearch', definition: {} }, ] ); }); diff --git a/packages/shell-api/src/collection.ts b/packages/shell-api/src/collection.ts index 6a8c47562..c74a033db 100644 --- a/packages/shell-api/src/collection.ts +++ b/packages/shell-api/src/collection.ts @@ -2315,8 +2315,13 @@ export default class Collection extends ShellApiWithMongoClass { // TODO(MONGOSH-1471): use SearchIndexDescription once available async createSearchIndex( indexName?: string | Document, + type?: 'search' | 'vectorSearch' | Document, definition?: Document ): Promise { + if (typeof type === 'object' && type !== null) { + definition = type; + type = undefined; + } if (typeof indexName === 'object' && indexName !== null) { definition = indexName; indexName = undefined; @@ -2329,6 +2334,9 @@ export default class Collection extends ShellApiWithMongoClass { [ { name: (indexName as string | undefined) ?? 'default', + // Omitting type when it is 'search' for compat with older servers + ...(type && + type !== 'search' && { type: type as 'search' | 'vectorSearch' }), definition: { ...definition }, }, ] @@ -2341,13 +2349,21 @@ export default class Collection extends ShellApiWithMongoClass { @apiVersions([]) // TODO(MONGOSH-1471): use SearchIndexDescription once available async createSearchIndexes( - specs: { name: string; definition: Document }[] + specs: { + name: string; + type?: 'search' | 'vectorSearch'; + definition: Document; + }[] ): Promise { this._emitCollectionApiCall('createSearchIndexes', { specs }); return await this._mongo._serviceProvider.createSearchIndexes( this._database._name, this._name, - specs + // Omitting type when it is 'search' for compat with older servers + specs.map(({ type, ...spec }) => ({ + ...spec, + ...(type && type !== 'search' && { type }), + })) ); } From 3086136f8bc98d43950b46316e0f67d224b1b0ab Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 28 Nov 2023 15:19:40 +0100 Subject: [PATCH 2/2] Apply suggestions from code review --- packages/shell-api/src/collection.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/shell-api/src/collection.spec.ts b/packages/shell-api/src/collection.spec.ts index 7cb2ede63..85ec1dfcf 100644 --- a/packages/shell-api/src/collection.spec.ts +++ b/packages/shell-api/src/collection.spec.ts @@ -2586,7 +2586,7 @@ describe('Collection', function () { }); context('with name, options and type !== search', function () { - it('calls serviceProvider.createIndexes', async function () { + it('calls serviceProvider.createSearchIndexes', async function () { await collection.createSearchIndex('my-index', 'vectorSearch', { mappings: { dynamic: true }, }); @@ -2606,7 +2606,7 @@ describe('Collection', function () { }); context('with name, options and type === search', function () { - it('calls serviceProvider.createIndexes', async function () { + it('calls serviceProvider.createSearchIndexes', async function () { await collection.createSearchIndex('my-index', 'search', { mappings: { dynamic: true }, }); @@ -2620,7 +2620,7 @@ describe('Collection', function () { }); context('with options and type but no name', function () { - it('calls serviceProvider.createIndexes', async function () { + it('calls serviceProvider.createSearchIndexes', async function () { await collection.createSearchIndex( { mappings: { dynamic: true } }, 'vectorSearch'