Reputation: 3882
I am creating my first backend project with Node.js, Express.js and Mongoose. I have a user, with a list of stocks objects [{symbol: amount}]
.
When the user wants to buy a stock, they send a POST request with stock, an amount, and a verb in this case 'buy'. In the Post, I take the stock and amount from the request body and add it to the User's stock list.
A request with
{stock: 'F', amount: '2', verb: 'buy'}
should add
{'F': '2'}
to the user's stocks. The problem is when I create and push the stock with
stockObject[stock] = amount;
user.stocks.push(stockObject);
user.stocks
becomes [{ _id: 54be8739dd63f94c0e000004 }]
instead of [{'F': '2'}]
, but when I make
stockObject={'symbol':stock, 'amount': amount}
and push that I will get
[{'symbol': 'F', 'amount': '2', _id: 54be8739dd63f94c0e000004}]
Why will Mongoose replace my data in the first case, but keep it in the second?
var UserSchema = new Schema({
id: String,
stocks: [{
symbol: String,
amount: Number
}]
});
router.route('/user/:user_id/action')
.post(function(req, res) {
User.findOne({
id: req.params.user_id
}, function(err, user) {
if (err) res.send(err);
var stock = req.body.stock;
var amount = req.body.amount;
var stockObject = {};
if (req.body.verb === 'buy') {
stockObject[stock] = amount;
}
user.stocks.push(stockObject);
user.save(function(err) {
res.json({
stocks: user.stocks
});
});
});
})
Upvotes: 1
Views: 2045
Reputation: 123513
The issue is that the first object you're trying to save:
console.log(stockObject);
// { 'F': '2' }
Doesn't match the Schema
you've defined for it:
{
symbol: String,
amount: Number
}
Mongoose normalizes objects it saves based on the Schema
, removing excess properties like 'F'
when it's expecting only 'symbol'
and 'amount'
.
if(req.body.verb === 'buy') {
stockObject.symbol = stock;
stockObject.amount = amount;
}
To get the output as [{"F": "2"}]
, you could .map()
the collection before sending it to the client:
res.json({
stocks: user.stocks.map(function (stock) {
// in ES6
// return { [stock.symbol]: stock.amount };
var out = {};
out[stock.symbol] = stock.amount;
return out;
});
});
Or, use the Mixed
type, as mentioned in "How do you use Mongoose without defining a schema?," that would allow you to store { 'F': '2' }
.
var UserSchema = new Schema({
id: String,
stocks: [{
type: Schema.Types.Mixed
}]
});
Upvotes: 3