diff --git a/source/index-management/index-management.md b/source/index-management/index-management.md index dd92e60b0c..7a19e14e21 100644 --- a/source/index-management/index-management.md +++ b/source/index-management/index-management.md @@ -664,7 +664,7 @@ interface IndexOptions { * @example For an index of name: 1, age: -1, the generated name would be "name_1_age_-1". */ name: String; - + /** * Optionally tells the index to only reference documents with the specified field in * the index. @@ -903,6 +903,9 @@ interface SearchIndexModel { // The name for this index, if present. name: Optional; + + // The type for this index, if present. Can be either "search" or "vectorSearch". + type: Optional; } interface SearchIndexOptions { diff --git a/source/index-management/index-management.rst b/source/index-management/index-management.rst index c2cda3423f..7cf4c49f2a 100644 --- a/source/index-management/index-management.rst +++ b/source/index-management/index-management.rst @@ -693,6 +693,16 @@ Common API Components */ name: String; + /** + * Optionally specify a type for the index. Defaults to "search" if not provided. + * Either "search" for regular search indexes or "vectorSearch" for vector search indexes. + * + * Note that to create a vector search index using a helper method, the type "vectorSearch" must be provided. + * + */ + type: String; + + /** * Optionally tells the index to only reference documents with the specified field in * the index. @@ -1149,3 +1159,4 @@ Changelog :2023-07-27: Add search index management clarifications. :2023-11-08: Clarify that ``readConcern`` and ``writeConcern`` must not be applied to search index management commands. +:2024-03-06: Update tests to include search index typing. \ No newline at end of file diff --git a/source/index-management/tests/README.md b/source/index-management/tests/README.md index 3598a81d36..2ca3c759c1 100644 --- a/source/index-management/tests/README.md +++ b/source/index-management/tests/README.md @@ -231,3 +231,108 @@ This test fails if it times out waiting for the deletion to succeed. of `true`. 6. Assert that `index` has a property `latestDefinition` whose value is `{ 'mappings': { 'dynamic': false } }` + +#### Case 7: Driver can successfully handle search index types when creating indexes + +01. Create a collection with the "create" command using a randomly generated name (referred to as `coll0`). + +02. Create a new search index on `coll0` with the `createSearchIndex` helper. Use the following definition: + + ```typescript + + { + name: 'test-search-index-case7-implicit', + definition: { + mappings: { dynamic: false } + } + } + ``` + +03. Assert that the command returns the name of the index: `"test-search-index-case7-implicit"`. + +04. Run `coll0.listSearchIndexes('test-search-index-case7-implicit')` repeatedly every 5 seconds until the following + condition is satisfied and store the value in a variable `index1`: + + - An index with the `name` of `test-search-index-case7-implicit` is present and the index has a field `queryable` + with a value of `true`. + +05. Assert that `index1` has a property `type` whose value is `search`. + +06. Create a new search index on `coll0` with the `createSearchIndex` helper. Use the following definition: + + ```typescript + + { + name: 'test-search-index-case7-explicit', + type: 'search', + definition: { + mappings: { dynamic: false } + } + } + ``` + +07. Assert that the command returns the name of the index: `"test-search-index-case7-explicit"`. + +08. Run `coll0.listSearchIndexes('test-search-index-case7-explicit')` repeatedly every 5 seconds until the following + condition is satisfied and store the value in a variable `index2`: + + - An index with the `name` of `test-search-index-case7-explicit` is present and the index has a field `queryable` + with a value of `true`. + +09. Assert that `index2` has a property `type` whose value is `search`. + +10. Create a new vector search index on `coll0` with the `createSearchIndex` helper. Use the following definition: + + ```typescript + + { + name: 'test-search-index-case7-vector', + type: 'vectorSearch', + definition: { + fields: [ + { + type: 'vector', + path: 'plot_embedding', + numDimensions: 1536, + similarity: 'euclidean', + }, + ] + } + } + ``` + +11. Assert that the command returns the name of the index: `"test-search-index-case7-vector"`. + +12. Run `coll0.listSearchIndexes('test-search-index-case7-vector')` repeatedly every 5 seconds until the following + condition is satisfied and store the value in a variable `index3`: + + - An index with the `name` of `test-search-index-case7-vector` is present and the index has a field `queryable` with + a value of `true`. + +13. Assert that `index3` has a property `type` whose value is `vectorSearch`. + +#### Case 8: Driver requires explicit type to create a vector search index + +1. Create a collection with the "create" command using a randomly generated name (referred to as `coll0`). + +2. Create a new vector search index on `coll0` with the `createSearchIndex` helper. Use the following definition: + + ```typescript + + { + name: 'test-search-index-case8-error', + definition: { + fields: [ + { + type: 'vector', + path: 'plot_embedding', + numDimensions: 1536, + similarity: 'euclidean', + }, + ] + } + } + ``` + +3. Assert that the command throws an exception containing the string "Attribute mappings missing" due to the `mappings` + field missing. diff --git a/source/index-management/tests/createSearchIndex.json b/source/index-management/tests/createSearchIndex.json index f9c4e44d3e..327cb61259 100644 --- a/source/index-management/tests/createSearchIndex.json +++ b/source/index-management/tests/createSearchIndex.json @@ -50,7 +50,8 @@ "mappings": { "dynamic": true } - } + }, + "type": "search" } }, "expectError": { @@ -73,7 +74,8 @@ "mappings": { "dynamic": true } - } + }, + "type": "search" } ], "$db": "database0" @@ -97,7 +99,8 @@ "dynamic": true } }, - "name": "test index" + "name": "test index", + "type": "search" } }, "expectError": { @@ -121,7 +124,68 @@ "dynamic": true } }, - "name": "test index" + "name": "test index", + "type": "search" + } + ], + "$db": "database0" + } + } + } + ] + } + ] + }, + { + "description": "create a vector search index", + "operations": [ + { + "name": "createSearchIndex", + "object": "collection0", + "arguments": { + "model": { + "definition": { + "fields": [ + { + "type": "vector", + "path": "plot_embedding", + "numDimensions": 1536, + "similarity": "euclidean" + } + ] + }, + "name": "test index", + "type": "vectorSearch" + } + }, + "expectError": { + "isError": true, + "errorContains": "Atlas" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "createSearchIndexes": "collection0", + "indexes": [ + { + "definition": { + "fields": [ + { + "type": "vector", + "path": "plot_embedding", + "numDimensions": 1536, + "similarity": "euclidean" + } + ] + }, + "name": "test index", + "type": "vectorSearch" } ], "$db": "database0" diff --git a/source/index-management/tests/createSearchIndex.yml b/source/index-management/tests/createSearchIndex.yml index 2e3cf50f8d..a32546cacf 100644 --- a/source/index-management/tests/createSearchIndex.yml +++ b/source/index-management/tests/createSearchIndex.yml @@ -26,7 +26,7 @@ tests: - name: createSearchIndex object: *collection0 arguments: - model: { definition: &definition { mappings: { dynamic: true } } } + model: { definition: &definition { mappings: { dynamic: true } } , type: 'search' } expectError: # This test always errors in a non-Atlas environment. The test functions as a unit test by asserting # that the driver constructs and sends the correct command. @@ -39,7 +39,7 @@ tests: - commandStartedEvent: command: createSearchIndexes: *collection0 - indexes: [ { definition: *definition } ] + indexes: [ { definition: *definition, type: 'search'} ] $db: *database0 - description: "name provided for an index definition" @@ -47,7 +47,7 @@ tests: - name: createSearchIndex object: *collection0 arguments: - model: { definition: &definition { mappings: { dynamic: true } } , name: 'test index' } + model: { definition: &definition { mappings: { dynamic: true } } , name: 'test index', type: 'search' } expectError: # This test always errors in a non-Atlas environment. The test functions as a unit test by asserting # that the driver constructs and sends the correct command. @@ -60,5 +60,27 @@ tests: - commandStartedEvent: command: createSearchIndexes: *collection0 - indexes: [ { definition: *definition, name: 'test index' } ] + indexes: [ { definition: *definition, name: 'test index', type: 'search' } ] + $db: *database0 + + - description: "create a vector search index" + operations: + - name: createSearchIndex + object: *collection0 + arguments: + model: { definition: &definition { fields: [ {"type": "vector", "path": "plot_embedding", "numDimensions": 1536, "similarity": "euclidean"} ] } + , name: 'test index', type: 'vectorSearch' } + expectError: + # This test always errors in a non-Atlas environment. The test functions as a unit test by asserting + # that the driver constructs and sends the correct command. + # The expected error message was changed in SERVER-83003. Check for the substring "Atlas" shared by both error messages. + isError: true + errorContains: Atlas + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + createSearchIndexes: *collection0 + indexes: [ { definition: *definition, name: 'test index', type: 'vectorSearch' } ] $db: *database0 diff --git a/source/index-management/tests/createSearchIndexes.json b/source/index-management/tests/createSearchIndexes.json index 3cf56ce12e..d91d7d9cf3 100644 --- a/source/index-management/tests/createSearchIndexes.json +++ b/source/index-management/tests/createSearchIndexes.json @@ -83,7 +83,8 @@ "mappings": { "dynamic": true } - } + }, + "type": "search" } ] }, @@ -107,7 +108,8 @@ "mappings": { "dynamic": true } - } + }, + "type": "search" } ], "$db": "database0" @@ -132,7 +134,8 @@ "dynamic": true } }, - "name": "test index" + "name": "test index", + "type": "search" } ] }, @@ -157,7 +160,70 @@ "dynamic": true } }, - "name": "test index" + "name": "test index", + "type": "search" + } + ], + "$db": "database0" + } + } + } + ] + } + ] + }, + { + "description": "create a vector search index", + "operations": [ + { + "name": "createSearchIndexes", + "object": "collection0", + "arguments": { + "models": [ + { + "definition": { + "fields": [ + { + "type": "vector", + "path": "plot_embedding", + "numDimensions": 1536, + "similarity": "euclidean" + } + ] + }, + "name": "test index", + "type": "vectorSearch" + } + ] + }, + "expectError": { + "isError": true, + "errorContains": "Atlas" + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "createSearchIndexes": "collection0", + "indexes": [ + { + "definition": { + "fields": [ + { + "type": "vector", + "path": "plot_embedding", + "numDimensions": 1536, + "similarity": "euclidean" + } + ] + }, + "name": "test index", + "type": "vectorSearch" } ], "$db": "database0" diff --git a/source/index-management/tests/createSearchIndexes.yml b/source/index-management/tests/createSearchIndexes.yml index db8f02e551..cac442cb87 100644 --- a/source/index-management/tests/createSearchIndexes.yml +++ b/source/index-management/tests/createSearchIndexes.yml @@ -48,7 +48,7 @@ tests: - name: createSearchIndexes object: *collection0 arguments: - models: [ { definition: &definition { mappings: { dynamic: true } } } ] + models: [ { definition: &definition { mappings: { dynamic: true } } , type: 'search' } ] expectError: # This test always errors in a non-Atlas environment. The test functions as a unit test by asserting # that the driver constructs and sends the correct command. @@ -61,7 +61,7 @@ tests: - commandStartedEvent: command: createSearchIndexes: *collection0 - indexes: [ { definition: *definition } ] + indexes: [ { definition: *definition, type: 'search'} ] $db: *database0 - description: "name provided for an index definition" @@ -69,7 +69,7 @@ tests: - name: createSearchIndexes object: *collection0 arguments: - models: [ { definition: &definition { mappings: { dynamic: true } } , name: 'test index' } ] + models: [ { definition: &definition { mappings: { dynamic: true } } , name: 'test index' , type: 'search' } ] expectError: # This test always errors in a non-Atlas environment. The test functions as a unit test by asserting # that the driver constructs and sends the correct command. @@ -82,5 +82,27 @@ tests: - commandStartedEvent: command: createSearchIndexes: *collection0 - indexes: [ { definition: *definition, name: 'test index' } ] + indexes: [ { definition: *definition, name: 'test index', type: 'search' } ] + $db: *database0 + + - description: "create a vector search index" + operations: + - name: createSearchIndexes + object: *collection0 + arguments: + models: [ { definition: &definition { fields: [ {"type": "vector", "path": "plot_embedding", "numDimensions": 1536, "similarity": "euclidean"} ] }, + name: 'test index' , type: 'vectorSearch' } ] + expectError: + # This test always errors in a non-Atlas environment. The test functions as a unit test by asserting + # that the driver constructs and sends the correct command. + # The expected error message was changed in SERVER-83003. Check for the substring "Atlas" shared by both error messages. + isError: true + errorContains: Atlas + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + createSearchIndexes: *collection0 + indexes: [ { definition: *definition, name: 'test index', type: 'vectorSearch' } ] $db: *database0