Skip to content

Discriminator indexes duplicated when schema has nested paths #15966

@Ju-NXH

Description

@Ju-NXH

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Mongoose version

9.1.3

Node.js version

24.13.0

MongoDB server version

7.0.28

Typescript version (if applicable)

No response

Description

When a discriminator schema is created using Base.discriminator() and both base and discriminator schemas share the same specs structure containing nested schemas, the discriminator's _indexes array gets populated with duplicate copies of the base schema's indexes. The number of duplicates equals the number of nested schema paths in the specs.

Steps to Reproduce

In this example: 3 base indexes × 3 nested schema paths = 9 indexes in the discriminator schema.

const mongoose = require('mongoose');

// Shared nested schema
const NESTED_SCHEMA = new mongoose.Schema({ 
  itemId: mongoose.Schema.Types.ObjectId 
}, { _id: false });

// Specs used by BOTH base and discriminator
const GENERIC_SPECS = {
  parentRef: { type: mongoose.Schema.Types.ObjectId },
  createdAt: Date,
  externalId: String,
  source: NESTED_SCHEMA,
  reference: NESTED_SCHEMA,
  comments: [{ value: String }]  // 3 nested schema paths total
};

function createSchema(collection, specs) {
  return new mongoose.Schema(specs, { collection });
}

async function main() {
  await mongoose.connect('mongodb://localhost:27017/test');

  const baseSchema = createSchema('Item', GENERIC_SPECS);
  baseSchema.index({ parentRef: 1, createdAt: -1 });
  baseSchema.index({ externalId: 1, parentRef: 1 });
  baseSchema.index({ 'source.itemId': 1, parentRef: 1 });

  const Base = mongoose.model('Item', baseSchema);

  const discSchema = createSchema('Item.typeA', GENERIC_SPECS);
  const Child = Base.discriminator('Item.typeA', discSchema, { clone: false });

  console.log('Base _indexes:', Base.schema._indexes.length);        // 3
  console.log('Discriminator _indexes:', discSchema._indexes.length); // 9 (expected: 3)

  // Indexes are tripled: [1,2,3, 1,2,3, 1,2,3]
  discSchema._indexes.forEach((idx, i) => console.log(i, JSON.stringify(idx[0])));

  // This fails because diffIndexes returns 9 duplicate indexes
  const { toCreate } = await Child.diffIndexes({ indexOptionsToCreate: true });
  await Child.createIndexes({ toCreate });

  await mongoose.disconnect();
}

main();

Stack Trace

MongoServerError: An existing index has the same name as the requested index. When index names are not specified, they are auto generated and can cause conflicts. Please refer to our documentation. Requested index: { v: 2, key: { parentRef: 1, createdAt: -1 }, name: "parentRef_1_createdAt_-1", partialFilterExpression: { __t: "Item.typeA" } }, existing index: { v: 2, key: { parentRef: 1, createdAt: -1 }, name: "parentRef_1_createdAt_-1" }
    at Connection.sendCommand (node_modules/mongodb/lib/cmap/connection.js:320:27)
    at process.processTicksAndRejections (node:internal/process/task_queues:103:5)
    at async Connection.command (node_modules/mongodb/lib/cmap/connection.js:344:26)
    at async Server.command (node_modules/mongodb/lib/sdam/server.js:208:29)
    at async tryOperation (node_modules/mongodb/lib/operations/execute_operation.js:215:32)
    at async executeOperation (node_modules/mongodb/lib/operations/execute_operation.js:80:16)
    at async Collection.createIndex (node_modules/mongodb/lib/collection.js:373:25)

Expected vs Actual

  • Expected: discSchema._indexes.length = 3
  • Actual: discSchema._indexes.length = 9 (multiplied by number of nested schema paths)

Expected Behavior

When creating a discriminator model, the discriminator schema's _indexes array should contain the same number of indexes as the base schema (3 indexes). The diffIndexes() method should return only the indexes that need to be created with discriminator-specific partialFilterExpression, without duplicates.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions