buunguyen / mongoose-deep-populate

Mongoose plugin to enable deep population of nested models ⛺
MIT License
469 stars 44 forks source link

deepPopulate with model specified in refPath #32

Closed simonccarter closed 9 years ago

simonccarter commented 9 years ago

I have 2 schemas, activities and notifications.

Model1:

var mongoose = require('mongoose');
var deepPopulate = require('mongoose-deep-populate')(mongoose);

var Schema = mongoose.Schema,
    ObjectId = Schema.ObjectId;

var model1schema = Schema({
    testModel2       : {
        type         :  ObjectId ,
        ref          :  'TestModel2'
    }
});

model1schema.plugin(deepPopulate);
module.exports = mongoose.model('TestModel1', model1schema);

Model2:

var mongoose = require('mongoose');
var deepPopulate = require('mongoose-deep-populate')(mongoose);

var schema = mongoose.Schema({
    actor_type      : String,
    actor           : {
        type        : mongoose.Schema.Types.ObjectId,
        refPath     : 'actor_type'
    }
});

schema.plugin(deepPopulate);
module.exports = mongoose.model('TestModel2', schema);

Queries are of the form:

    TestModel1
        .find({some condition})
        .deepPopulate('testModel2.actor')

I've tried different variations on this query.

When querying TestModel1, i'm able to populate the testModel2 field, but not able to populate sub documents, such as TestModel1.TestModel2.actor.

Yet, if i'm doing a find directly on TestModel2, I can populate those documents (just using populate(), not the deepPopulate plugin).

I'm not sure if this is a bug, missing feature, or something wrong with something else, but just wanted to check here I was not doing anything wrong.

Any help, even if telling me this is not supported by deepPopulate, would be great.

Thanks,

KayBeSee commented 8 years ago

Was this ever resolved? I have the same question / issue.

buunguyen commented 8 years ago

Can you add a failed test?

KayBeSee commented 8 years ago

I have the following models:

Notes:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;

var deepPopulate = require('mongoose-deep-populate')(mongoose);

require('./chapter');
require('./user');
require('./activism_event');
require('./student');

var note_schema = new Schema({
  user: {type: ObjectId, ref: 'User'},
  parent: {
    kind: String,
    item: { type: ObjectId, refPath: 'parent.kind' }
  },
  date_created: Date,
  date_modified: Date,
  message: String
  });

note_schema.plugin(deepPopulate);

module.exports = mongoose.model('Note', note_schema);

Chapter:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;

var chapter_schema = new Schema({
  school_name: String,
  city: String,
  state: String,
  region: String,
  status: String,
  tier: String,
  date_created: Date,
  date_modified: Date,
  reply_date: Date,
  referral: String,
  state_chair_assigned: String,
  chapter_facebook_url: String,
  president: {
    first_name: String,
    last_name: String,
    email: String,
    phone: Number,
    street_1: String,
    street_2: String,
    city: String,
    state: String,
    zipcode: String,
    facebook_url: String
  },
  free_speech: {
    rating: String,
    zone: Boolean,
    target: Boolean,
    status: String
  }
});

module.exports = mongoose.model('Chapter', chapter_schema);

and Activism_Events:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;
require('./chapter');

var activism_event_schema = new Schema({
  chapter: {type: ObjectId, ref: 'Chapter'},
  date_created: Date,
  date_modified: Date,
  date_executed: Date,
  type: String,
  status: String,
  blog_post_url: String
});

module.exports = mongoose.model('ActivismEvent', activism_event_schema);

In notes, if parent.kind = "chapter" then it will refPath to the chapter model and populate the data with that id in the chapter collection. If parent.kind="activismevent" then it will populate from the activismevent collection.

This behavior works fine when I use the traditional "populate" methods but when I try using this deep-populate package it doesn't work.

Here's an example json output when I use deeppopulate:

[
  {
    "_id": "56f0a74796e6e1e13c6fbfbf",
    "user": {
      "_id": "56e5f0fe9c82097604be21ff",
      "first_name": "Kevin",
      "last_name": "Mulcrone",
      "phone": 7088059743,
      "email": "KayBeSee@gmail.com",
      "facebook_url": "http://facebook.com/kaybesee",
      "date_created": "1967-01-02T05:00:00.000Z",
      "picture_url": "https://scontent.xx.fbcdn.net/hphotos-xtp1/t31.0-8/12829311_10207220825471340_897303930952526274_o.jpg",
      "region": "Midwest",
      "role": "State Chair",
      "__v": 0
    },
    "date_created": "2016-03-22T02:00:39.769Z",
    "date_modified": "2016-03-22T02:00:39.770Z",
    "message": "Test",
    "__v": 0,
    "parent": {
     "item": "56f0a70796e6e1e13c6fbfbc",
      "kind": "ActivismEvent"
    }
},
  {
    "_id": "56f0a78c0c8358873f24b385",
    "user": {
      "_id": "56e5f0fe9c82097604be21ff",
      "first_name": "Kevin",
      "last_name": "Mulcrone",
      "phone": 7088059743,
      "email": "KayBeSee@gmail.com",
      "facebook_url": "http://facebook.com/kaybesee",
      "date_created": "1967-01-02T05:00:00.000Z",
      "picture_url": "https://scontent.xx.fbcdn.net/hphotos-xtp1/t31.0-8/12829311_10207220825471340_897303930952526274_o.jpg",
      "region": "Midwest",
      "role": "State Chair",
      "__v": 0
      },
    "date_created": "2016-03-22T02:01:48.493Z",
    "date_modified": "2016-03-22T02:01:48.493Z",
    "message": "This chapter is sweeeeeet.",
    "__v": 0,
    "parent": {
      "item": "56d701c9475c6206a205a908",
      "kind": "Chapter"
    }
  }
]

Here is the notes.controller I'm using to populate that. I'm not sure if having deepPopulate defined in my notes-model file has any effect on it (I'm not sure why it would).

exports.getAll = function(done) {
  Note.find({ }).deepPopulate('user, parent.item').exec( function (err, notes) {
    if (err) return done(err, null);
    done(null, notes);
  });
}
simonccarter commented 8 years ago

@KayBeSee From memory, and having had a look at the deep-populate source code, I seem to remember the issue being that the type of document/model of the field being deep populated is set at the collection level, not the document level, and would require a rewrite/refactor to account for document specific rewrites. This was a while ago, and someone more familiar with the code, i.e., @buunguyen, might like to advise.

dglavask commented 6 years ago

I have the same problem. Not resolved yet.