Skip to content

Commit ae35908

Browse files
DRIVERS-2549: add search index management helpers (#1423)
1 parent a839581 commit ae35908

15 files changed

+1133
-10
lines changed

.github/workflows/check_schema_version.sh

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,7 @@ exitCode=0
55

66
# $1 - takes a single argument of the path to the JSON file containing a schemaVersion key at the top level.
77
function get_schema_version() {
8-
node << EOF
9-
const { readFileSync } = require('fs')
10-
const { load } = require('js-yaml')
11-
console.log(load(readFileSync("./$1", { encoding: 'utf-8' })).schemaVersion)
12-
EOF
8+
js-yaml $1 | jq -r .schemaVersion
139
}
1410

1511
function get_all_schemaVersion_defining_files () {

.github/workflows/unified-test-format-schema-check.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ jobs:
2222
node-version: lts/*
2323
- name: Install dependencies
2424
run: |
25-
npm install -g ajv-cli
26-
npm install js-yaml
25+
npm install -g ajv-cli js-yaml
2726
- name: Check unified format test files against schema
2827
working-directory: source/unified-test-format/tests
2928
run: make

source/client-side-encryption/client-side-encryption.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2118,9 +2118,11 @@ endSessions BYPASS
21182118
startSession BYPASS
21192119
create BYPASS
21202120
createIndexes BYPASS
2121+
createSearchIndexes BYPASS
21212122
drop BYPASS
21222123
dropDatabase BYPASS
21232124
dropIndexes BYPASS
2125+
dropSearchIndex BYPASS
21242126
killCursors BYPASS
21252127
listCollections BYPASS
21262128
listDatabases BYPASS
@@ -2132,6 +2134,7 @@ killAllSessions BYPASS
21322134
killSessions BYPASS
21332135
killAllSessionsByPattern BYPASS
21342136
refreshSessions BYPASS
2137+
updateSearchIndex BYPASS
21352138
======================== ===========
21362139
21372140
All AUTOENCRYPT commands are sent to mongocryptd, even if there is no

source/index-management/index-management.rst

Lines changed: 184 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,188 @@ Example::
852852
> a
853853
[ "_id_", "ty_1", "l_2dsphere", "ts_1" ]
854854
855+
--------------
856+
Search Indexes
857+
--------------
858+
859+
Server 7.0 introduced three new server commands and a new aggregation stage to facilitate management of search indexes. Drivers MUST provide
860+
an API similar to the existing index management API specifically for search indexes. Drivers MAY choose to implement either the standard
861+
API or the index view API.
862+
863+
Search Index Management Helper Options
864+
--------------------------------------
865+
866+
There are currently no supported options for any of the search index management commands. To future proof
867+
drivers implementations so that any options added in the future do not constitute a breaking change to drivers,
868+
empty options structs have been added as placeholders. If a driver's language has a mechanism to add options
869+
in a non-breaking manner (i.e., method overloading) drivers MAY omit the empty options structs from their
870+
search index management helpers.
871+
872+
``listSearchIndexes`` is implemented using an aggregation pipeline. The list helper MUST support a driver's aggregation
873+
options as outline in the `CRUD specification <https://github.com/mongodb/specifications/blob/master/source/crud/crud.rst#read>`_. Drivers MAY combine the aggregation options with
874+
any future ``listSearchIndexes`` stage options, if that is idiomatic for a driver's language.
875+
876+
Notes
877+
-----
878+
879+
The search index commands are asynchronous and return from the server before the index is successfully updated, created or dropped.
880+
In order to determine when an index has been created / updated, users are expected to run the ``listSearchIndexes`` repeatedly
881+
until index changes appear.
882+
883+
An example, from Javascript:
884+
885+
.. code:: typescript
886+
887+
const name = await collection.createSearchIndex({ definition: { ... fill out definition } })
888+
while (!(await collection.listSearchIndexes({ name }).hasNext())) {
889+
await setTimeout(1000);
890+
}
891+
892+
Common Interfaces
893+
-----------------
894+
895+
.. code:: typescript
896+
897+
interface SearchIndexModel {
898+
// The definition for this index.
899+
definition: Document;
900+
901+
// The name for this index, if present.
902+
name: Optional<string>;
903+
}
904+
905+
/**
906+
* The following interfaces are empty but are provided as placeholders for drivers that cannot
907+
* add options in a non-breaking manner, if options are added in the future.
908+
*/
909+
interface CreateSearchIndexOptions {}
910+
interface UpdateSearchIndexOptions {}
911+
interface ListSearchIndexOptions {}
912+
interface DropSearchIndexOptions {}
913+
914+
Standard API for Search Indexes
915+
-------------------------------
916+
917+
.. code:: typescript
918+
919+
interface Collection {
920+
/**
921+
* Convenience method for creating a single search index.
922+
*
923+
* @return The name of the created search index
924+
*
925+
* @note Drivers MAY opt to implement this method signature, the signature that
926+
* takes an SearchIndexModel as a parameter, or for those languages with method
927+
* overloading MAY decide to implement both.
928+
*/
929+
createSearchIndex(name: String, definition: Document, options: Optional<CreateSearchIndexOptions>): String;
930+
931+
/**
932+
* Convenience method for creating a single index.
933+
*
934+
* @return The name of the created search index
935+
*
936+
* @note Drivers MAY opt to implement this method signature, the signature that
937+
* takes an name and a definition as parameters, or for those languages with method
938+
* overloading MAY decide to implement both.
939+
*/
940+
createSearchIndex(model: SearchIndexModel, options: Optional<CreateSearchIndexOptions>): String;
941+
942+
/**
943+
* Creates multiple search indexes on the collection.
944+
*
945+
* @return An iterable of the newly created index names.
946+
*/
947+
createSearchIndexes(models: Iterable<SearchIndexModel>, options: CreateSearchIndexOptions): Iterable<String>;
948+
949+
/**
950+
* Updates the search index with the given name to use the provided
951+
* definition.
952+
*/
953+
updateSearchIndex(name: String, definition: Document, options: Optional<UpdateSearchIndexOptions>): void;
954+
955+
/**
956+
* Drops the search index with the given name.
957+
*/
958+
dropSearchIndex(name: String, options: Optional<DropSearchIndexOptions>): void;
959+
960+
/**
961+
* Gets index information for one or more search indexes in the collection.
962+
*
963+
* If name is not specified, information for all indexes on the specified collection will be returned.
964+
*/
965+
listSearchIndexes(name: Optional<String>, aggregationOptions: Optional<AggregationOptions>, listIndexOptions: Optional<ListSearchIndexOptions>): Cursor<Document>;
966+
}
967+
968+
Index View API for Search Indexes
969+
---------------------------------
970+
971+
.. code:: typescript
972+
973+
interface Collection {
974+
/**
975+
* Returns the search index view for this collection.
976+
*/
977+
searchIndexes(name: Optional<String>, aggregateOptions: Optional<AggregationOptions>, options: Optional<ListSearchIndexesOptions>): SearchIndexView;
978+
}
979+
980+
interface SearchIndexView extends Iterable<Document> {
981+
/**
982+
* Enumerates the index information for all search indexes in the collection.
983+
*
984+
* @note For drivers that cannot make the IndexView iterable, they MUST implement a list
985+
* method. See below.
986+
*/
987+
iterator(): Iterator<Document>;
988+
989+
/**
990+
* For drivers that cannot make SearchIndexView iterable, they MUST implement this method to
991+
* return a list of indexes. In the case of async drivers, this MAY return a Future<Cursor>
992+
* or language/implementation equivalent.
993+
*/
994+
list(): Cursor<Document>;
995+
996+
997+
/**
998+
* This is a convenience method for creating a single index.
999+
*
1000+
* @return The name of the created index.
1001+
*
1002+
* @note Drivers MAY opt to implement this method signature, the signature that
1003+
* takes an SearchIndexModel as a parameter, or for those languages with method
1004+
* overloading MAY decide to implement both.
1005+
*/
1006+
createOne(name: String, definition: Document, options: Optional<CreateSearchIndexOptions>): String;
1007+
1008+
/**
1009+
* This is a convenience method for creating a single index.
1010+
*
1011+
* @return The name of the created index.
1012+
*
1013+
* @note Drivers MAY opt to implement this method signature, the signature that
1014+
* takes an name and a definition as parameters, or for those languages with method
1015+
* overloading MAY decide to implement both.
1016+
*/
1017+
createOne(model: SearchIndexModel, options: Optional<CreateSearchIndexOptions>): String;
1018+
1019+
/**
1020+
* Creates multiple search indexes in the collection.
1021+
*
1022+
* @return The names of the created indexes.
1023+
*/
1024+
createMany(models: Iterable<SearchIndexModel>, options: Optional<CreateSearchIndexOptions>): Iterable<String>;
1025+
1026+
/**
1027+
* Drops a single search index from the collection by the index name.
1028+
*/
1029+
dropOne(name: String, options: Optional<DropSearchIndexOptions>): Result;
1030+
1031+
/**
1032+
* Updates a single search index from the collection by the index name.
1033+
*/
1034+
updateOne(name: String, options: Optional<UpdateSearchIndexOptions>): Result;
1035+
}
1036+
8551037
---------
8561038
Q & A
8571039
---------
@@ -908,5 +1090,6 @@ Changelog
9081090
:2022-04-18: Added the ``clustered`` attribute to ``IndexOptions`` in order to
9091091
support clustered collections.
9101092
:2022-10-05: Remove spec front matter and reformat changelog.
911-
:2023-5-10: Merge index enumeration and index management specs and get rid of references
1093+
:2023-05-10: Merge index enumeration and index management specs and get rid of references
9121094
to legacy server versions.
1095+
:2023-05-18: Add the search index management API.
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
{
2+
"description": "createSearchIndex",
3+
"schemaVersion": "1.4",
4+
"createEntities": [
5+
{
6+
"client": {
7+
"id": "client0",
8+
"useMultipleMongoses": false,
9+
"observeEvents": [
10+
"commandStartedEvent"
11+
]
12+
}
13+
},
14+
{
15+
"database": {
16+
"id": "database0",
17+
"client": "client0",
18+
"databaseName": "database0"
19+
}
20+
},
21+
{
22+
"collection": {
23+
"id": "collection0",
24+
"database": "database0",
25+
"collectionName": "collection0"
26+
}
27+
}
28+
],
29+
"runOnRequirements": [
30+
{
31+
"minServerVersion": "7.0.0",
32+
"topologies": [
33+
"replicaset",
34+
"load-balanced",
35+
"sharded"
36+
],
37+
"serverless": "forbid"
38+
}
39+
],
40+
"tests": [
41+
{
42+
"description": "no name provided for an index definition",
43+
"operations": [
44+
{
45+
"name": "createSearchIndex",
46+
"object": "collection0",
47+
"arguments": {
48+
"model": {
49+
"definition": {
50+
"mappings": {
51+
"dynamic": true
52+
}
53+
}
54+
}
55+
},
56+
"expectError": {
57+
"isError": true
58+
}
59+
}
60+
],
61+
"expectEvents": [
62+
{
63+
"client": "client0",
64+
"events": [
65+
{
66+
"commandStartedEvent": {
67+
"command": {
68+
"createSearchIndexes": "collection0",
69+
"indexes": [
70+
{
71+
"definition": {
72+
"mappings": {
73+
"dynamic": true
74+
}
75+
}
76+
}
77+
],
78+
"$db": "database0"
79+
}
80+
}
81+
}
82+
]
83+
}
84+
]
85+
},
86+
{
87+
"description": "name provided for an index definition",
88+
"operations": [
89+
{
90+
"name": "createSearchIndex",
91+
"object": "collection0",
92+
"arguments": {
93+
"model": {
94+
"definition": {
95+
"mappings": {
96+
"dynamic": true
97+
}
98+
},
99+
"name": "test index"
100+
}
101+
},
102+
"expectError": {
103+
"isError": true
104+
}
105+
}
106+
],
107+
"expectEvents": [
108+
{
109+
"client": "client0",
110+
"events": [
111+
{
112+
"commandStartedEvent": {
113+
"command": {
114+
"createSearchIndexes": "collection0",
115+
"indexes": [
116+
{
117+
"definition": {
118+
"mappings": {
119+
"dynamic": true
120+
}
121+
},
122+
"name": "test index"
123+
}
124+
],
125+
"$db": "database0"
126+
}
127+
}
128+
}
129+
]
130+
}
131+
]
132+
}
133+
]
134+
}

0 commit comments

Comments
 (0)