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

.populate() does not work from a base schema, using discriminators, when the related collection is defined in the polymorphic child. #2719

Closed
ericsaboia opened this issue Feb 26, 2015 · 15 comments
Milestone

Comments

@ericsaboia
Copy link

mongoose version: "^3.8.19"
related to: #1647

When you use discriminators, and want to query from the base schema, populating some related collection, which was defined in the polymorphic child schema, the query runs, but the result goes without the related population objects.

Example:

var mongoose = require('mongoose')
  , Schema = mongoose.Schema
  , util = require('util')
;

function BaseSchema() {
  Schema.apply(this, arguments);
  this.add( { name: String } );
}

util.inherits(BaseSchema, Schema);

var EventSchema = new BaseSchema();

var ConversionEvent = new BaseSchema({
  owner: { type: Schema.Types.ObjectId, ref: 'User', required: true }
});

var Base = mongoose.model('Event', EventSchema),
var Conversion = Base.discriminator('Conversion', ConversionEvent);

Conversion.create({
  name: 'test',
  owner: user._id
}, function (err, conversion) {

  Base.find().populate('owner').exec(function (err, bases) {
    // Owner object isen't attached
    console.log(bases); 
  });

});
@ericsaboia ericsaboia changed the title .populate() does not work from a base schema, using discriminators, when the related entity is defined in the specialized schema. .populate() does not work from a base schema, using discriminators, when the related collection is defined in the polymorphic child. Feb 26, 2015
@vkarpov15
Copy link
Collaborator

Hmm can you let me know what EventSchema looks like? Makes it much easier for me when I can just run your repro example as is.

@vkarpov15 vkarpov15 added this to the 3.8.25 milestone Feb 27, 2015
@ericsaboia
Copy link
Author

It's just an instance of the BaseSchema, I've updated the example.

@vkarpov15 vkarpov15 modified the milestones: 3.8.26, 3.8.25 Mar 12, 2015
@vkarpov15 vkarpov15 added confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. and removed confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. labels Mar 16, 2015
@vkarpov15
Copy link
Collaborator

@ericsaboia this is by design. The schema underlying Base doesn't have an owner field, so .populate('owner') is invalid. Conversion.find().populate('owner') works as intended.

@vkarpov15 vkarpov15 removed this from the 3.8.26 milestone Mar 16, 2015
@ericsaboia
Copy link
Author

Are you sure? because even when you query by the Base model, the returned object it's a instance of its child, and contains all the child fields:

For example:

Base.find({}, function(err, events) {
    expect.ok(events[0] instanceof Conversion);       // true
   console.log(events[0].owner) // Owner ObjectId
});

So in my opinion it's worth the implementation.

@vkarpov15
Copy link
Collaborator

True, but when you call populate() it explicitly uses the base model and so doesn't know about 'owner'. It's a quirk, but one that makes sense IMO. What's your use case?

@ericsaboia
Copy link
Author

It's a feed on a social app. My base model it's called Activity, and then I have a lot of specialised types of Activity (checkin, post, promotion, and so on)

Some of my Activity's children have specific relations, so it's not declared at the base model (Activity).

At my feed service, I need to return a list of all kind of activities, with the populates necessary to fill the client.

Ps: the result is cached, that's why I decided to keep the call to "populate" instead of copy the necessary fields from the related collections.

@vkarpov15
Copy link
Collaborator

So in 3.x there's no way to populate from multiple models - one populate() call <=> one model. @chetverikov added the ability to populate from multiple models into 4.x so this may be more feasible now. I'll re-open this issue and see how feasible it is for a future release.

@vkarpov15 vkarpov15 reopened this Mar 17, 2015
@vkarpov15 vkarpov15 added this to the 4.2 milestone Mar 17, 2015
@vkarpov15 vkarpov15 modified the milestones: 4.0.0, 4.2 Mar 19, 2015
vkarpov15 added a commit that referenced this issue Mar 19, 2015
@diegodfsd
Copy link

Hi @vkarpov15

I'm with the same problem but i saw that you close the issue this means that now should be possible populate a child of a specialisation?

@vkarpov15
Copy link
Collaborator

Yep see PR #2773 courtesy of @chetverikov

@diegodfsd
Copy link

Well,

I'm using Mongoose 4.0.1 and I can't populate a collection in one specialisation.

'use strict';

const Mongoose = require('mongoose'),
      Util = require('util');

function BaseSchema() {
  Mongoose.Schema.apply(this, arguments);

  this.add({
    name     : { type: String, required: true },
    date     : { type: Date, required: true },
    period   : { start : { type: String, required: true },
                 end   : { type: String, required: true } 
               }
  });
}

Util.inherits(BaseSchema, Mongoose.Schema);

let Event = new BaseSchema({});


module.exports = {
  schema: BaseSchema,
  model: Mongoose.model('Event', Event)
};
'use strict';

const Mongoose = require('mongoose'),
      Event = require('./event');

let Talk = new Event.schema({ 
  pin            : { type: String, required: true, index: { unique: true } },
  totalAttendees : { type: Number },
  speakers       : [{ type: Mongoose.Schema.Types.ObjectId, ref: 'Speaker' }],
  surveys        : [{ type: Mongoose.Schema.Types.ObjectId, ref: 'Survey' }],
  questions      : [{ type: Mongoose.Schema.Types.ObjectId, ref: 'Question' }]
});

module.exports = Event.model.discriminator('Talk', Talk);

Here is how I'm trying using populate unsuccessfully.

const  Event = require('./../models/event');

Event.find({}).populate('surveys').exec(function(err, events) {
  if (err) {
    console.dir(err);
  }
  console.dir(results[0].surveys); // this always returns undefined same when there is some item in the collection
});

This is an example of my data collection events

{ "_id" : ObjectId("551b71e01e4e40bc2b168884"), "name" : "Meetup rails", "date" : ISODate("2015-04-01T00:00:00Z"), "pin" : "0004", "__t" : "Talk", "period" : { "start" : "11:00", "end" : "12:00" }, "questions" : [ ], "surveys" : [ ObjectId("551b71ef1e4e40bc2b168885") ], "speakers" : [ ], "__v" : 1 }

This is the output with query result

{ _id: 551b71e01e4e40bc2b168884,
  name: 'Meetup rails',
  date: Tue Mar 31 2015 21:00:00 GMT-0300 (BRT),
  pin: '0004',
  __t: 'Talk',
  questions: [],
  surveys: [],
  speakers: [],
  __v: 1,
  period: { start: '11:00', end: '12:00' } }

I can't see where is my mistake or if the fix did not work.

@vkarpov15 vkarpov15 reopened this Apr 1, 2015
@vkarpov15 vkarpov15 modified the milestones: 4.0.2, 4.0.0 Apr 1, 2015
@chetverikov
Copy link
Contributor

@vkarpov15 @diegodfsd
Oh +( Forgive me please.
I made a mistake
Indeed, I made a mistake and wrote two lines incorrectly +( But I already corrected this problem!
#2825
corrected

@diegodfsd
Copy link

Do you will release a new version with this fix when?

@ericsaboia
Copy link
Author

cheers @chetverikov!

@diegodfsd
Copy link

No problem @chetverikov

@aforty
Copy link

aforty commented Apr 11, 2016

Edit: opened separate issue instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants