Skip to content

Error with Virtual Populating Embedded Discriminators with Dynamic "ref" #6554

@jimmytsao

Description

@jimmytsao

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

What is the current behavior?
When trying to do a virtual population on an embedded discriminator with a dynamic ref, mongoose errors with:

MissingSchemaError: Schema hasn't been registered for model "ref".
Use mongoose.model(name, schema)
    at new MissingSchemaError (/Users/mac/Documents/code/playground/mongoose-tests/node_modules/mongoose/lib/error/missingSchema.js:20:11)
    at NativeConnection.Connection.model (/Users/mac/Documents/code/playground/mongoose-tests/node_modules/mongoose/lib/connection.js:708:11)
    at getModelsMapForPopulate (/Users/mac/Documents/code/playground/mongoose-tests/node_modules/mongoose/lib/model.js:3728:20)
    at populate (/Users/mac/Documents/code/playground/mongoose-tests/node_modules/mongoose/lib/model.js:3254:21)
    at _populate (/Users/mac/Documents/code/playground/mongoose-tests/node_modules/mongoose/lib/model.js:3224:5)
    at utils.promiseOrCallback.cb (/Users/mac/Documents/code/playground/mongoose-tests/node_modules/mongoose/lib/model.js:3197:5)
    at Object.promiseOrCallback (/Users/mac/Documents/code/playground/mongoose-tests/node_modules/mongoose/lib/utils.js:222:14)
    at Function.Model.populate (/Users/mac/Documents/code/playground/mongoose-tests/node_modules/mongoose/lib/model.js:3196:16)
    at cb (/Users/mac/Documents/code/playground/mongoose-tests/node_modules/mongoose/lib/query.js:1347:17)
    at result (/Users/mac/Documents/code/playground/mongoose-tests/node_modules/mongodb/lib/utils.js:414:17)
    at executeCallback (/Users/mac/Documents/code/playground/mongoose-tests/node_modules/mongodb/lib/utils.js:406:9)
    at handleCallback (/Users/mac/Documents/code/playground/mongoose-tests/node_modules/mongodb/lib/utils.js:128:55)
    at self.close (/Users/mac/Documents/code/playground/mongoose-tests/node_modules/mongodb/lib/cursor.js:904:60)
    at handleCallback (/Users/mac/Documents/code/playground/mongoose-tests/node_modules/mongodb/lib/utils.js:128:55)
    at completeClose (/Users/mac/Documents/code/playground/mongoose-tests/node_modules/mongodb/lib/cursor.js:1043:14)
    at _endSession (/Users/mac/Documents/code/playground/mongoose-tests/node_modules/mongodb/lib/cursor.js:1053:35)

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

The error seems to happen once the ref on the virtual config is converted to a function:

const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost/mongoosetest')
mongoose.connection.once('open', () => {

  const Schema = mongoose.Schema

  // Generate Users Model
  const userSchema = new Schema({ employeeId: Number, name: String })
  const UserModel = mongoose.model('Users', userSchema, 'users')

  // Generate Embedded Discriminators
  const eventSchema = new Schema(
    { message: String },
    { discriminatorKey: 'kind'}
  );

  const batchSchema = new Schema({
    events: [eventSchema]
  });

  const docArray = batchSchema.path('events'); 

  // First embedded discriminator schema
  const clickedSchema = new Schema(
    {
      element: { type: String },
      users: [{}]
    },
    {
      toJSON: { virtuals: true},
      toObject: { virtuals: true}
    }
  );

  // Add virtual to first embedded discriminator schema for virtual population
  clickedSchema.virtual('users_$', {
    // ref: 'Users',    //<--- This will work
    ref: doc => {      //<--- Using this will yield the error
      return doc.events[0].users[0].refKey
    },
    // ref:  () => 'Users',     //<--- This will yield the same error as above
    localField: 'users.ID',
    foreignField: 'employeeId'
  })
  
  const Clicked = docArray.discriminator('Clicked', clickedSchema);

  // Second embedded discriminator
  const Purchased = docArray.discriminator('Purchased', new Schema({
    product: { type: String }
  }));

  const Batch = mongoose.model('EventBatch', batchSchema);

  // Generate Items
  const user = { employeeId: 1, name: 'Test name' }
  const batch = {
    events: [
      { kind: 'Clicked', element: '#hero', message: 'hello', users: [{ ID: 1, refKey: 'Users' }] },
      { kind: 'Purchased', product: 'action-figure-1', message: 'world' }
    ]
  };

  // Clearing out the collections before creating items
  Promise.all([ UserModel.remove({}), Batch.remove({}) ])
  .then(() => Promise.all([UserModel.create(user), Batch.create(batch)]))
  .then(function(){
    Batch.find({})
      // Populate virtual field of embedded discriminator
      .populate('events.users_$') 
      .lean()
      .then(results => {
        console.log(JSON.stringify(results, null, 2))
      })
  })
})

What is the expected behavior?
Expected to not error and to have events.users_$ populated:

[
  {
    "_id": "5b1569d023f8d233f421a34a",
    "events": [
      {
        "users": [
          {
            "ID": 1,
            "refKey": "Users"
          }
        ],
        "_id": "5b1569d023f8d233f421a34c",
        "kind": "Clicked",
        "element": "#hero",
        "message": "hello",
        "users_$": [
          {
            "_id": "5b1569d023f8d233f421a349",
            "employeeId": 1,
            "name": "Test name",
            "__v": 0
          }
        ]
      },
      {
        "_id": "5b1569d023f8d233f421a34b",
        "kind": "Purchased",
        "product": "action-figure-1",
        "message": "world",
        "users_$": []
      }
    ],
    "__v": 0
  }
]

Please mention your node.js, mongoose and MongoDB version.
Mongoose: 5.1.3
Node: 8.11.1
Mongo: 3.6.4

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions