I'm working on an app where users can create and account and make trivia games. User
has a property called games
which is a collection of Game
id's that that User
instance has created. When I create a Game
instance, before I return the response (JSON
of new Game
instance), I find the User
instance and use a User
schema method to add the newly created Games
id to the collection of game ids in the User
's games property. It seems to work when I create a game, I was able to log the instance of User
with the array reflecting the newly added Game
id.
But then when I try to get the User
via localhost:4000/users/USER_ID
the games
property remains empty.
Here is my User
Model.
const mongoose = require("mongoose");
const validator = require("validator");
const bcrypt = require('bcryptjs')
const jwt = require('jsonwebtoken')
const Schema = mongoose.Schema;
let User = new Schema({
username: {
type: String, required: true, trim: true, default: null,
unique: true
},
password: {
type: String, required: true, trim: true, default: null
},
games:{
type: Array, required: false, default: []
}
});
User.methods.addGame = async function(id) {
const user = this;
var games = user.games;
games.push(id);
user.games = games;
user.save()
return user
}
module.exports = mongoose.model('User', User);
Here is my root /users
route and my /users/:id
route.
userRoutes.route('/').get(function(req, res){
User.find(function(err, users){
if(err){
res.status(400).send(err);
} else {
res.json(users)
}
});
});
userRoutes.route('/:id').get(function(req, res){
User.findById(req.params.id, function(err, user){
if(err){
res.status(400).send(err)
} else {
if (user){
res.status(200).json(user);
} else {
res.status(400).send('user not found :(')
}
}
});
});
And here is my add
game route.
gameRoutes.route('/add').post( async function(req, res){
try {
var user = await User.findOne({ _id: req.body.owner })
let game = new Game(req.body);
if (!user){
res.status(400).send('user not found.')
} else {
await game.save()
await user.addGame(game._id);
if (!game){
res.status(400).send('game cannot be created');
} else {
res.status(200).json(game);
}
}
} catch (error) {
res.status(500).send(error);
}
});
Finally, here is the data that is logged when I use mongoose.set('debug', true)
and create a game.
Mongoose: users.findOne({ _id: ObjectId("5daca0171febbb25f2c929dd") },
{ projection: {} })
Mongoose: games.insertOne({ questions: [ { id: 0, qTitle: 'When is
Independence Day?', qAnswers: [ { aId: 0, aContent: 'July 18th' }, {
aId: 1, aContent: 'July 19th' }, { aId: 2, aContent: 'July 30th' }, {
aId: 3, aContent: 'July 4th' } ], answer: 3, correct: null }, { id: 1,
qTitle: 'When is Christmas Day?', qAnswers: [ { aId: 0, aContent:
'July 18th' }, { aId: 1, aContent: 'July 19th' }, { aId: 2, aContent:
'December 25th' }, { aId: 3, aContent: 'December 31st' } ], answer: 2,
correct: null } ], qTime: null, expDate: null, isPrivate: true,
isClosed: false, _id: ObjectId("5db5c2fe96960e318ae8f60f"), name:
'poppie', __v: 0 }, { session: null })
Mongoose: users.updateOne({ _id: ObjectId("5daca0171febbb25f2c929dd"),
__v: 19 }, { '$set': { games: [ ObjectId("5db5c2fe96960e318ae8f60f") ]
},
'$inc': { __v: 1 } }, { session: undefined })
Right after creating a game, if I go to /localhost:4000/users
I see the resulting list of User
's.
[{
"username": "matt_cee",
"password":
"$2a$10$/ySrwkMxaHGO24FOEst3NuqpG4iQi78BUCSkl4Hb.RmjTIwynR3l.",
"games": [
"5db5c2fe96960e318ae8f60f"
]
}]
As you can see, the games
array contains the newly created game's id. I am able to log the updated User
in the /add
games route but when accessing the /:id
user route, the returned User
instance has an empty array for the games property.
I was able to figure out the issue was that I wasn't providing the property in the right format. Here is how my Game
model was set up.
let Game = new Schema({
owner: {
id: { type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
username: {type: String}
}
},
name:{
type: String
},
questions: {
type: Array
}
});
The problem was I was trying to update the User
by adding the id of the newly created Game
to user.games
but the owner property wasn't populating properly because I was only passing the user
's id not the username. Below is my updated game model.
let Game = new Schema({
owner: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true
},
name:{
type: String
},
questions: {
type: Array
}
})
Special thanks to @user753642 with who's help I was able to better structure my code and debug the data.