Skip to content

Commit c9a6b9b

Browse files
Merge pull request #75 from geturbackend/copilot/fix-pre-existing-index-rollback
fix(injectModel): fix pre-existing index rollback and required-field duplicate precheck
2 parents 71d9deb + c7b7371 commit c9a6b9b

1 file changed

Lines changed: 50 additions & 32 deletions

File tree

packages/common/src/utils/injectModel.js

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ function clearCompiledModel(connection, collectionName) {
144144

145145
function 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

172172
async 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

Comments
 (0)