These are the schemes:
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} });
You tried aggregation instead of filling. The aggregate makes it much easier to populate the embedded data with $lookup . Try the code below.
UPDATE
Topic.aggregate([{$unwind: "$thoughts"},{ $lookup: {from: 'users', localField: 'thoughts.author', foreignField: '_id', as: 'thoughts.author'}},{$sort:{{popularity : -1, date: -1}}}],function(err,topics){ console.log(topics)
Explanation
$ unwind : Deconstructs an array field from input documents to output a document for each element.
$ lookup : the $ lookup stage matches the equality between the field from the input documents and the field from the documents of the “merged” collection. Search does work with the public.
$ lookup works like
from : this indicates which collection to fill in the data from. ( users in this scenario).
localField : this is the local field to be filled. ( thoughts.author in this case).
foreignField : this is the external field present in the collection from which data needs to be populated ( _id in the users collection in this scenario).
how : this field is like what you want to display the combined value as. (this projects thoughts. author as a document of thoughts. author).
Hope this works.