I have a mongoDB database which is generated using a script that uses only the node.js mongoDB driver without mongoose. Later on, in the application, I want to use mongoose to load a document and have a reference be populated automatically; however, this only ever returns null.
Imagine a task which contains sub-items which each have a title and an assigned person. The assigned person, in this case, is the reference I want to have populated, so the reference lives in an object inside an array in the task schema.
The following code (requiring npm install mongodb mongoose) reproduces the problem (watch out, it destroys a local database named test if you have one already):
const mongodb = require('mongodb');
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
(async () => {
// Step 1: Insert data. This is done using the mongodb driver without mongoose.
const db = await mongodb.MongoClient.connect('mongodb://localhost/test');
await db.dropDatabase();
await db.collection('persons').insertOne({ name: 'Joe' });
const joe = await db.collection('persons').findOne({ name: 'Joe' });
await db.collection('tasks').insertOne({ items: [{ title: 'Test', person: joe._id }] });
await db.close();
// ================
// Step 2: Create the schemas and models.
const PersonSchema = new Schema({
name: String,
});
const Person = mongoose.model('Person', PersonSchema);
const TaskSchema = new Schema({
items: [{
title: String,
person: { type: Schema.Types.ObjectId, ref: 'Person' },
}],
});
const Task = mongoose.model('Task', TaskSchema);
// ================
// Step 3: Try to query the task and have it populated.
mongoose.connect('mongodb://localhost/test');
mongoose.Promise = Promise;
const myTask = await Task.findOne({}).populate('items.person');
// :-( Unfortunately this prints only
// { _id: "594283a5957e327d4896d135", items: [ { title: 'Test', person: null } ] }
console.log(JSON.stringify(myTask, null, 4));
mongoose.connection.close();
})();
The expected output would be
{ _id: "594283a5957e327d4896d135", items: [ { title: 'Test', person: { _id: "594283a5957e327d4896d134", name: "Joe" } } ] }
I have verified that the two _ids actually match using mongo shell:
> db.persons.find({})
{ "_id" : ObjectId("594283a5957e327d4896d134"), "name" : "Joe" }
> db.tasks.find({})
{ "_id" : ObjectId("594283a5957e327d4896d135"), "items" : [ { "title" : "Test", "person" : ObjectId("594283a5957e327d4896d134") } ] }
What am I doing wrong when attempting to populate person? I am using mongoose 4.10.6 and mongodb 2.2.28.
.exec()after thepopulatecall doesn't work either, neither does using a callback instead ofawait.