Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Virtual Population of Field on a Nested Embedded Discriminator Not Working #6411

Closed
jimmytsao opened this issue May 1, 2018 · 1 comment
Closed
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Milestone

Comments

@jimmytsao
Copy link

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

What is the current behavior?
When trying to perform a virtual population of a field on an embedded discriminator that is at the root of the model, everything is populated correctly. However, when I try do the same on a nested embedded discriminator, the results are not populated. See working and non-working example in repro script section.

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

Here's are some examples:

Virtual Population WORKING When Embedded Discriminator Field Is At The Root

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] });  // <-- Embedded Discrminator at root
  const docArray = batchSchema.path('events');

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

  // Add virtual to first embedded discriminator schema for virtual population
  clickedSchema.virtual('users_$', {
    ref: 'Users',
    localField: 'users',
    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: [1] },
      { kind: 'Purchased', product: 'action-figure-1', message: 'world' }
    ]
  };

  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(results) )
    })
 
  /*  Correct Results with "events.users_$" populated
  [
      {
          "_id": "5ae8ccc0daad6931954ceebf",
          "events": [
              {
                  "users": [
                      1
                  ],
                  "_id": "5ae8ccc0daad6931954ceec1",
                  "kind": "Clicked",
                  "element": "#hero",
                  "message": "hello",
                  "users_$": [
                      {
                          "_id": "5ae8ccc0daad6931954ceebe",
                          "employeeId": 1,
                          "name": "Test name",
                          "__v": 0
                      }
                  ]
              },
              {
                  "_id": "5ae8ccc0daad6931954ceec0",
                  "kind": "Purchased",
                  "product": "action-figure-1",
                  "message": "world"
              }
          ],
          "__v": 0
      }
  ]
  */
})

Virtual Population NOT WORKING When Embedded Discriminator Field Is Nested

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({
    nested: { // <--- Added Nesting
      events: [eventSchema]
    }
  });

  const docArray = batchSchema.path('nested.events'); // <--- Added Nesting

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

  // Add virtual to first embedded discriminator schema for virtual population
  clickedSchema.virtual('users_$', {
    ref: 'Users',
    localField: 'users',
    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 = {
    nested: {   // <--- Added Nesting
      events: [
        { kind: 'Clicked', element: '#hero', message: 'hello', users: [1] },
        { kind: 'Purchased', product: 'action-figure-1', message: 'world' }
      ]
    }
  };

  Promise.all([UserModel.create(user), Batch.create(batch)])
    .then(function(){
      Batch.find({})
        // Populate virtual field of embedded discriminator
        .populate('nested.events.users_$') // <--- Added Nesting
        .lean()
        .then(results => console.log(results) )
    })
  }
)
  /*  Results. Expected "nested.events.users_$" to be populated
  [
    {
        "_id": "5ae8d2f453e7c03deb827438",
        "nested": {
            "events": [
                {
                    "users": [
                        1
                    ],

                    "_id": "5ae8d2f453e7c03deb82743a",
                    "kind": "Clicked",
                    "element": "#hero",
                    "message": "hello"
                },
                {
                    "_id": "5ae8d2f453e7c03deb827439",
                    "kind": "Purchased",
                    "product": "action-figure-1",
                    "message": "world"
                }
            ]
        },
        "__v": 0
    }
  ]
  */

What is the expected behavior?
The virtual field at "nested.events.users_$" is populated

Please mention your node.js, mongoose and MongoDB version.
node: 10.0.0
mongoose: 5.0.17
mongodb: 3.6.4

@jimmytsao jimmytsao changed the title Virtual Population of Field on a Nest Embedded Discriminator Not Working Virtual Population of Field on a Nested Embedded Discriminator Not Working May 2, 2018
@vkarpov15 vkarpov15 added this to the 5.0.18 milestone May 4, 2018
@vkarpov15 vkarpov15 added the confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. label May 4, 2018
@vkarpov15
Copy link
Collaborator

Thanks for reporting, will fix ASAP 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Projects
None yet
Development

No branches or pull requests

2 participants