Really not clear what your issue here is exactly, so it's probably best to just demonstrate with a self contained listing. You really should not need to change anything in the provided code other than possibly the uri
for the host and database namespace and maybe authentication credentials.
You should choose a database namespace that is different from what your application is using, as the self contained test here is meant to be destructive of any existing data.
Modern nodejs releases past 7.x:
const { Schema } = mongoose = require('mongoose');
const uri = 'mongodb://localhost/schooling';
mongoose.Promise = global.Promise;
mongoose.set('debug', true);
const userSchema = new Schema({
firstName: String,
lastName: String,
email: String,
});
const assignmentSchema = new Schema({
studentIds: [{ type: Schema.Types.ObjectId, ref: 'User' }],
name: String,
startDate: { type: Date, default: Date.now }
});
const User = mongoose.model('User', userSchema);
const Assignment = mongoose.model('Assignment', assignmentSchema);
const log = data => console.log(JSON.stringify(data, undefined, 2));
(async function() {
try {
const conn = await mongoose.connect(uri);
await Promise.all(Object.entries(conn.models).map(([k,m]) => m.remove()));
let users = await User.insertMany(
["aaa", "bbb"].map(el => ({ firstName: el, lastName: el, email: `${el}@example.com` }) )
);
log(users);
await Assignment.create({
studentIds: users,
name: 'test 1'
});
let results = await Assignment.aggregate([
{ "$lookup": {
"from": User.collection.name,
"localField": "studentIds",
"foreignField": "_id",
"as": "studentDetails"
}}
]);
log(results);
mongoose.disconnect();
} catch(e) {
console.error(e);
} finally {
process.exit();
}
})();
Or back a few versions:
const mongoose = require('mongoose'),
Schema = mongoose.Schema;
const uri = 'mongodb://localhost/schooling';
mongoose.Promise = global.Promise;
mongoose.set('debug', true);
const userSchema = new Schema({
firstName: String,
lastName: String,
email: String,
});
const assignmentSchema = new Schema({
studentIds: [{ type: Schema.Types.ObjectId, ref: 'User' }],
name: String,
startDate: { type: Date, default: Date.now }
});
const User = mongoose.model('User', userSchema);
const Assignment = mongoose.model('Assignment', assignmentSchema);
const log = data => console.log(JSON.stringify(data, undefined, 2));
mongoose.connect(uri)
.then(conn => Promise.all(Object.keys(conn.models).map(k => conn.models[k].remove())))
.then(() =>User.insertMany(
["aaa", "bbb"].map(el => ({ firstName: el, lastName: el, email: `${el}@example.com` }) )
))
.then(users => {
log(users);
return Assignment.create({
studentIds: users,
name: 'test 1'
})
})
.then(() => Assignment.aggregate([
{ "$lookup": {
"from": User.collection.name,
"localField": "studentIds",
"foreignField": "_id",
"as": "studentDetails"
}}
]))
.then( results => log(results) )
.then(() => mongoose.disconnect() )
.catch( e => console.error(e) )
.then(() => process.exit());
You should set that up in it's own project folder with no other dependencies and essentially just npm install
based on the following package.json
being present in that folder along with the listing:
{
"name": "schooling",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"mongoose": "^5.0.15"
}
}
So that's really just mongoose
and it's direct dependencies installed and nothing else.
Either one should give you output along the lines of this:
Mongoose: users.remove({}, {})
Mongoose: assignments.remove({}, {})
Mongoose: users.insertMany([ { _id: 5ad71e821d7f7b05c0316bb0, firstName: 'aaa', lastName: 'aaa', email: 'aaa@example.com', __v: 0 }, { _id: 5ad71e821d7f7b05c0316bb1, firstName: 'bbb', lastName: 'bbb', email: 'bbb@example.com', __v: 0 } ], {})
[
{
"_id": "5ad71e821d7f7b05c0316bb0",
"firstName": "aaa",
"lastName": "aaa",
"email": "aaa@example.com",
"__v": 0
},
{
"_id": "5ad71e821d7f7b05c0316bb1",
"firstName": "bbb",
"lastName": "bbb",
"email": "bbb@example.com",
"__v": 0
}
]
Mongoose: assignments.insert({ studentIds: [ ObjectId("5ad71e821d7f7b05c0316bb0"), ObjectId("5ad71e821d7f7b05c0316bb1") ], _id: ObjectId("5ad71e821d7f7b05c0316bb2"), name: 'test 1', startDate: new Date("Wed, 18 Apr 2018 10:31:30 GMT"), __v: 0 })
Mongoose: assignments.aggregate([ { '$lookup': { from: 'users', localField: 'studentIds', foreignField: '_id', as: 'studentDetails'
} } ], {})
[
{
"_id": "5ad71e821d7f7b05c0316bb2",
"studentIds": [
"5ad71e821d7f7b05c0316bb0",
"5ad71e821d7f7b05c0316bb1"
],
"name": "test 1",
"startDate": "2018-04-18T10:31:30.839Z",
"__v": 0,
"studentDetails": [
{
"_id": "5ad71e821d7f7b05c0316bb0",
"firstName": "aaa",
"lastName": "aaa",
"email": "aaa@example.com",
"__v": 0
},
{
"_id": "5ad71e821d7f7b05c0316bb1",
"firstName": "bbb",
"lastName": "bbb",
"email": "bbb@example.com",
"__v": 0
}
]
}
]
That clearly shows you the items from the "users"
collection are being returned into the array target by the $lookup
.
If nothing else, this should provide you with a basis to diagnose what is going wrong in your current environment as you can see how things are being done by comparison.