Skip to content

path discriminator does not treat different item differently when populate #8452

@kpkonghk01

Description

@kpkonghk01

Do you want to request a feature or report a bug?
bug

What is the current behavior?
populate an item that should not populate by discriminator setting

If the current behavior is a bug, please provide the steps to reproduce.

const mongoose = require('mongoose');
const { Schema, ObjectId, model } = mongoose;

mongoose.connect(
  'mongodb://localhost:27017',
  {
    keepAlive: true,
    dbName: 'localTest',
    useNewUrlParser: true,
    useFindAndModify: false,
    useCreateIndex: true,
    autoIndex: true,
  },
);
mongoose.set('debug', true);

(async () => {
  const ImageSchema = new mongoose.Schema({
    imageName: {
      type: String,
      required: true
    }
  });
  const Image = mongoose.model('Image', ImageSchema);

  const TextSchema = new mongoose.Schema({
    textName: {
      type: String,
      required: true
    }
  });
  const Text = mongoose.model('Text', TextSchema);

  const ItemSchema = new Schema({
    objectType: {
      type: String,
    },
  }, {
    _id: false,
  });

  const ItemSchemaA = new Schema({
    data: {
      type: ObjectId,
      refPath: 'list.objectType',
    },
    objectType: {
      type: String,
      enum: ['Image', 'Text'],
    },
  }, {
    _id: false,
  });

  const ItemSchemaB = new Schema({
    data: {
      sourceId: {
        type: Number,
        required: true,
      },
    },
    objectType: {
      type: String,
      enum: ['ExternalSourceA', 'ExternalSourceB'],
    },
  }, {
    _id: false,
  });

  const ExampleSchema = new Schema({
    test: {
      type: String,
    },
    list: [{
      type: ItemSchema,
      required: false
    }],
  });
  ExampleSchema.path('list').discriminator('ExtendA', ItemSchemaA);
  ExampleSchema.path('list').discriminator('ExtendB', ItemSchemaB);
  const Example = model('Example', ExampleSchema);

  const image = await Image.create({
    imageName: '00image',
  });
  const text = await Text.create({
    textName: '00text',
  });

  await Example.create({
    test: '02',
    list: [
      {
        __t: 'ExtendA',
        message: 'i01',
        data: image._id,
        objectType: 'Image',
      },
      {
        __t: 'ExtendA',
        message: 't01',
        data: text._id,
        objectType: 'Text',
      },
      {
        __t: 'ExtendB',
        message: 'm02',
        data: {
          sourceId: 123
        },
        objectType: 'ExternalSourceA',
      }],
  });
  const query = Example
    .find()
    .populate({
      path: 'list.data',
    })
    .lean()

  // Error occurs here and the message as shown below:
  // "Schema hasn't been registered for model "ExternalSourceA".
  // Use mongoose.model(name, schema)"
  const results = await query.exec();
  return results;
})().then(
  async result => {
    await mongoose.disconnect();
    process.exit(0);
  },
  async _ => {
    console.log(_);
    await mongoose.disconnect();
    process.exit(1);
  }
)

What is the expected behavior?
Do not try to populate items of ItemSchemaB and return the original data

What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version.
node: v10.17.0
mongoDB: 4.2.1
mongoose: 5.7.13

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-bugWe've confirmed this is a bug in Mongoose and will fix it.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions