@@ -144,7 +144,7 @@ function clearCompiledModel(connection, collectionName) {
144144
145145function getUniqueFieldFilter ( fieldKey , isRequired ) {
146146 if ( isRequired ) {
147- return { [ fieldKey ] : { $exists : true } } ;
147+ return { } ; // scan ALL docs, including those missing the field
148148 }
149149
150150 return { [ fieldKey ] : { $exists : true , $ne : null } } ;
@@ -170,44 +170,62 @@ async function findDuplicates(Model, fieldKey, isRequired) {
170170}
171171
172172async function createUniqueIndexes ( Model , fields = [ ] ) {
173- for ( const field of fields ) {
174- if ( ! field . unique ) continue ;
175- if ( ! UNIQUE_SUPPORTED_TYPES_SET . has ( field . type ) ) continue ;
173+ const createdIndexes = [ ] ;
176174
177- const normalizedKey = normalizeKey ( field . key ) ;
178- if ( ! normalizedKey ) continue ;
179-
180- const duplicates = await findDuplicates (
181- Model ,
182- normalizedKey ,
183- ! ! field . required ,
184- ) ;
185-
186- if ( duplicates . length > 0 ) {
187- const examples = duplicates
188- . slice ( 0 , 3 )
189- . map ( ( d ) => JSON . stringify ( d . _id ) )
190- . join ( ", " ) ;
191-
192- throw new Error (
193- `Cannot create unique index on '${ normalizedKey } '. ${ duplicates . length } duplicate values exist.${ examples ? ` Examples: ${ examples } ` : "" } ` ,
175+ const existingIndexes = await Model . collection . indexes ( ) ;
176+ const existingIndexNames = new Set ( existingIndexes . map ( ( idx ) => idx . name ) ) ;
177+
178+ try {
179+ for ( const field of fields ) {
180+ if ( ! field . unique ) continue ;
181+ if ( ! UNIQUE_SUPPORTED_TYPES_SET . has ( field . type ) ) continue ;
182+
183+ const normalizedKey = normalizeKey ( field . key ) ;
184+ if ( ! normalizedKey ) continue ;
185+
186+ const duplicates = await findDuplicates (
187+ Model ,
188+ normalizedKey ,
189+ ! ! field . required ,
194190 ) ;
195- }
196191
197- const indexName = `unique_${ normalizedKey } _1` ;
192+ if ( duplicates . length > 0 ) {
193+ const examples = duplicates
194+ . slice ( 0 , 3 )
195+ . map ( ( d ) => JSON . stringify ( d . _id ) )
196+ . join ( ", " ) ;
198197
199- const indexOptions = {
200- unique : true ,
201- name : indexName ,
202- } ;
198+ throw new Error (
199+ `Cannot create unique index on ' ${ normalizedKey } '. ${ duplicates . length } duplicate values exist. ${ examples ? ` Examples: ${ examples } ` : "" } ` ,
200+ ) ;
201+ }
203202
204- if ( ! field . required ) {
205- indexOptions . partialFilterExpression = {
206- [ normalizedKey ] : { $exists : true , $ne : null } ,
203+ const indexName = `unique_${ normalizedKey } _1` ;
204+
205+ const indexOptions = {
206+ unique : true ,
207+ name : indexName ,
207208 } ;
208- }
209209
210- await Model . collection . createIndex ( { [ normalizedKey ] : 1 } , indexOptions ) ;
210+ if ( ! field . required ) {
211+ indexOptions . partialFilterExpression = {
212+ [ normalizedKey ] : { $exists : true , $ne : null } ,
213+ } ;
214+ }
215+
216+ const createdName = await Model . collection . createIndex (
217+ { [ normalizedKey ] : 1 } ,
218+ indexOptions ,
219+ ) ;
220+ if ( ! existingIndexNames . has ( createdName ) ) {
221+ createdIndexes . push ( createdName ) ;
222+ }
223+ }
224+ } catch ( err ) {
225+ for ( const indexName of createdIndexes ) {
226+ await Model . collection . dropIndex ( indexName ) . catch ( ( ) => { } ) ;
227+ }
228+ throw err ;
211229 }
212230}
213231
0 commit comments