简体   繁体   中英

Why is Mongoose replacing key/value pair in an object with _id?

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
                });
            });

        });
    })

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
    }]
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM