Reputation: 255
I am using Mongoose and MongoDB v. 6.4.1. I have defined a document collection with embedded subdocuments using the following Mongoose schemas:
import mongoose, { Collection } from 'mongoose';
const connectStr = 'mongodb://localhost/appdb';
mongoose.set('useFindAndModify', false);
//Open connection to database
mongoose.connect(connectStr, {useNewUrlParser: true, useUnifiedTopology: true})
.then(
() => {console.log(`Connected to ${connectStr}.`)},
err => {console.error(`Error connecting to ${connectStr}: ${err}`)}
);
//Define schema that maps to a document in the Users collection in the appdb
//database.
const Schema = mongoose.Schema;
const roundSchema = new Schema({
date: {type: Date, required: true},
course: {type: String, required: true},
type: {type: String, required: true, enum: ['practice','tournament']},
holes: {type: Number, required: true, min: 1, max: 18},
strokes: {type: Number, required: true, min: 1, max: 300},
minutes: {type: Number, required: true, min: 1, max: 240},
seconds: {type: Number, required: true, min: 0, max: 60},
SGS: {type: Number,
default: function(){return (this.strokes * 60) + (this.minutes * 60) + this.seconds}
},
notes: {type: String, required: true}
});
const userSchema = new Schema({
id: {type: String, required: true}, //unique identifier for user
password: String, //unencrypted password (for now!)
displayName: {type: String, required: true}, //Name to be displayed within app
authStrategy: {type: String, required: true}, //strategy used to authenticate, e.g., github, local
profileImageUrl: {type: String, required: true}, //link to profile image
rounds: [roundSchema],
securityQuestion: {type: String},
securityAnswer: {type: String, required: function() {return this.securityQuestion ? true: false}}
});
//Convert schema to model
const User = mongoose.model("User",userSchema);
In an Express.js GET route, I am using the following code to query for a specific document:
try {
let thisUser = await User.findOne({id: req.params.userId});
console.log("thisUser: " + JSON.stringify(thisUser));
if (!thisUser) {
return res.status(400).send("No user account with specified userId was found in database.");
} else {
return res.status(200).json(thisUser.rounds);
}
} catch (err) {
console.log(err);
return res.status(400).message("Unexpected error occurred when looking up user in database: " + err);
}
My console.log statement confirms that the above route in fact obtains the desired document, e.g.:
thisUser: {"_id":"5e6704234f3864318caedd12","id":"[email protected]","password":"GoCougs20","displayName":"[email protected]","authStrategy":"local","profileImageUrl":"https://www.gravatar.com/avatar/4b565c54d37b3f5ad4caa1c129e865b8","securityQuestion":"First pet?","securityAnswer":"Daisy","__v":0,"rounds":[]}
When I look at this same document in MongoDB Compass Community, I can confirm that its rounds
subdocument array has several elements:
However, as shown in the console.log
output above, rounds
is coming back as an empty array. I have confirmed that (a) rounds
is in fact an array (using Array.isArray()
) and that (b) rounds
has no elements (thisUser.rounds.length === 0
).
Shouldn't I be able to access all of the subdocuments through thisUser.rounds
? What have I done wrong?
Upvotes: 1
Views: 614
Reputation: 255
I have discovered a solution. I changed:
let thisUser = await User.findOne({id: req.params.userId});
to
let thisUser = await User.findOne({id: req.params.userId}).lean();
Miraculously, thisuser.rounds
was no longer empty. It instead contained all of the array elements I could see when I inspected the document in MongoDB Compass Community!
While this solution worked, I do not know why it worked. If anyone could help me understand what's going on here, I'd appreciate it!
Upvotes: 1