@@ -59,7 +59,10 @@ function isIndexDirection(x: any): x is IndexDirection {
59
59
60
60
/** @public */
61
61
export type IndexSpecification = OneOrMore <
62
- string | [ string , IndexDirection ] | { [ key : string ] : IndexDirection }
62
+ | string
63
+ | [ string , IndexDirection ]
64
+ | { [ key : string ] : IndexDirection }
65
+ | Map < string , IndexDirection >
63
66
> ;
64
67
65
68
/** @public */
@@ -87,7 +90,7 @@ export interface IndexDescription
87
90
> {
88
91
collation ?: CollationOptions ;
89
92
name ?: string ;
90
- key : Document ;
93
+ key : Document | Map < string , IndexDirection > ;
91
94
}
92
95
93
96
/** @public */
@@ -131,31 +134,39 @@ export interface CreateIndexesOptions extends CommandOperationOptions {
131
134
hidden ?: boolean ;
132
135
}
133
136
137
+ function isSingleIndexTuple ( t : unknown ) : t is [ string , IndexDirection ] {
138
+ return Array . isArray ( t ) && t . length === 2 && isIndexDirection ( t [ 1 ] ) ;
139
+ }
140
+
134
141
export function makeIndexSpec ( indexSpec : IndexSpecification , options : any ) : IndexDescription {
135
142
function getFieldHash ( indexSpec : IndexSpecification ) {
136
- let fieldHash : Map < string , IndexDirection > = new Map ( ) ;
143
+ const fieldHash : Map < string , IndexDirection > = new Map ( ) ;
137
144
138
145
let indexSpecArr : IndexSpecification [ ] ;
139
146
140
- // wrap in array if needed
141
- if ( ! Array . isArray ( indexSpec ) || ( indexSpec . length === 2 && isIndexDirection ( indexSpec [ 1 ] ) ) ) {
147
+ // Wrap indexSpec in array if needed
148
+ if ( ! Array . isArray ( indexSpec ) || isSingleIndexTuple ( indexSpec ) ) {
142
149
indexSpecArr = [ indexSpec ] ;
143
150
} else {
144
151
indexSpecArr = indexSpec ;
145
152
}
146
153
147
- // iterate through array and handle different types
148
- indexSpecArr . forEach ( ( f : any ) => {
149
- if ( 'string' === typeof f ) {
150
- fieldHash . set ( f , 1 ) ;
151
- } else if ( Array . isArray ( f ) ) {
152
- fieldHash . set ( f [ 0 ] , f [ 1 ] ) ;
153
- } else if ( isObject ( f ) ) {
154
- for ( const [ key , value ] of Object . entries ( f ) ) {
154
+ // Iterate through array and handle different types
155
+ for ( const spec of indexSpecArr ) {
156
+ if ( 'string' === typeof spec ) {
157
+ fieldHash . set ( spec , 1 ) ;
158
+ } else if ( Array . isArray ( spec ) ) {
159
+ fieldHash . set ( spec [ 0 ] , spec [ 1 ] ) ;
160
+ } else if ( spec instanceof Map ) {
161
+ for ( const [ key , value ] of spec ) {
162
+ fieldHash . set ( key , value ) ;
163
+ }
164
+ } else if ( isObject ( spec ) ) {
165
+ for ( const [ key , value ] of Object . entries ( spec ) ) {
155
166
fieldHash . set ( key , value ) ;
156
167
}
157
168
}
158
- } ) ;
169
+ }
159
170
160
171
return fieldHash ;
161
172
}
@@ -225,9 +236,32 @@ export class CreateIndexesOperation<
225
236
this . options = options ?? { } ;
226
237
this . collectionName = collectionName ;
227
238
228
- this . indexes = indexes ;
239
+ // Ensure we generate the correct name if the parameter is not set
240
+ const normalizedIndexes = [ ] ;
241
+ for ( const userIndex of indexes ) {
242
+ const key =
243
+ userIndex . key instanceof Map ? userIndex . key : new Map ( Object . entries ( userIndex . key ) ) ;
244
+ const index : Omit < IndexDescription , 'key' > & { key : Map < string , IndexDirection > } = {
245
+ ...userIndex ,
246
+ key
247
+ } ;
248
+ if ( index . name == null ) {
249
+ const keys = [ ] ;
250
+
251
+ for ( const [ name , direction ] of index . key ) {
252
+ keys . push ( `${ name } _${ direction } ` ) ;
253
+ }
254
+
255
+ // Set the name
256
+ index . name = keys . join ( '_' ) ;
257
+ }
258
+ normalizedIndexes . push ( index ) ;
259
+ }
260
+ this . indexes = normalizedIndexes ;
229
261
}
230
262
263
+ /* TODO: create name in the parent class constructor */
264
+ /* create a type assertion to stop typescript errors */
231
265
override execute (
232
266
server : Server ,
233
267
session : ClientSession | undefined ,
@@ -238,10 +272,9 @@ export class CreateIndexesOperation<
238
272
239
273
const serverWireVersion = maxWireVersion ( server ) ;
240
274
241
- // Ensure we generate the correct name if the parameter is not set
242
- for ( let i = 0 ; i < indexes . length ; i ++ ) {
275
+ for ( const index of indexes ) {
243
276
// Did the user pass in a collation, check if our write server supports it
244
- if ( indexes [ i ] . collation && serverWireVersion < 5 ) {
277
+ if ( index . collation && serverWireVersion < 5 ) {
245
278
callback (
246
279
new MongoCompatibilityError (
247
280
`Server ${ server . name } , which reports wire version ${ serverWireVersion } , ` +
@@ -250,17 +283,6 @@ export class CreateIndexesOperation<
250
283
) ;
251
284
return ;
252
285
}
253
-
254
- if ( indexes [ i ] . name == null ) {
255
- const keys = [ ] ;
256
-
257
- for ( const name in indexes [ i ] . key ) {
258
- keys . push ( `${ name } _${ indexes [ i ] . key [ name ] } ` ) ;
259
- }
260
-
261
- // Set the name
262
- indexes [ i ] . name = keys . join ( '_' ) ;
263
- }
264
286
}
265
287
266
288
const cmd : Document = { createIndexes : this . collectionName , indexes } ;
0 commit comments