Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Populate nested array in mongoose - Node.js

These are my schemas (Topic is parent and contains a list of 'Thought's):

var TopicSchema = new mongoose.Schema({
  title: { type: String, unique: true },
  category: String,
  thoughts: [ThoughtSchema]
}, {
  timestamps: true,
  toObject: {virtuals: true},
  toJSON: {virtuals: true}
});

var ThoughtSchema = new mongoose.Schema({
  text: String,
  author: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
  votes:[{
    _id:false,
    voter: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
    up: Boolean,
    date: {type: Date, default: Date.now}
  }]
}, {
  timestamps: true,
  toObject: {virtuals: true},
  toJSON: {virtuals: true}
});

....

I am trying to read the thought's author and change my get Topic api like this:

...
  var cursor = Topic.find(query).populate({
    path: 'thoughts',
    populate: {
      path: 'author',
      model: 'User'
    }
  }).sort({popularity : -1, date: -1});

  return cursor.exec()
    .then(respondWithResult(res))
    .catch(handleError(res));
...

But the author is null.. i also do not get any error in the console. What is wrong here?

Edit: Actually i do not need the Thought as a schema, it does not have its own collection in database. It will be saved in topics. But in order to use timestamps option with thoughts, i needed to extract its contents to a new local schema ThoughtSchema. But i have now defined the contents of thoughtSchema directly in the thoughts array of topics, it still does not work.

Edit2: This is the cursor object just before it is executed. Unfortunately i cannot debug in Webstorm, this is a screenshot from node inspector:

enter image description here

like image 253
akcasoy Avatar asked Jun 11 '16 08:06

akcasoy


1 Answers

Did you try using Model.populate?

Topic.find(query).populate('thoughts')
.sort({popularity : -1, date: -1})
.exec(function(err, docs) {
   // Multiple population per level
  if(err) return callback(err);
  Thought.populate(docs, {
    path: 'thoughts.author',
    model: 'User'
  },
  function(err, populatedDocs) {
    if(err) return callback(err);
    console.log(populatedDocs);
  });
});

UPDATE:
You can try with deep populate like this:

Topic.find(query).populate({
  path: 'thoughts',
  populate: {
    path: 'author',
    model: 'User'
  }
})
.sort({popularity : -1, date: -1})
.exec(function(err, docs) {
  if(err) return callback(err);
  console.log(docs);
});
like image 196
pasine Avatar answered Oct 20 '22 00:10

pasine