Reputation: 308
Hello i am trying to make a caculate field in mongoDB, however i get this error: MongoError: The dollar ($) prefixed field '$add' in '$add' is not valid for storage.
This is the code:
router.post('/char1btn', ensureAuthenticated, function(req, res) {
const {
MongoClient
} = require("mongodb");
//Replace the uri string with your MongoDB deployment's connection string.
const uri =
'mongodb+srv://test:[email protected]/Databasetest?retryWrites=true&w=majority';
const client = new MongoClient(uri);
async function run() {
try {
await client.connect();
const database = client.db("Databasetest");
const collection = database.collection("users");
//create a filter for charactername to update
const filter = {
characterimg: ""
};
// this option instructs the method to create a document if no documents match the filter
const options = {
upsert: false
};
const updateDoc = {
$set: {
health: 150,
attack: 3,
defence: 3,
endurance: 10,
characterimg: "https://i.ibb.co/MPg2SMp/Apocaliptic1.png",
},
$set: {
$add: ["$power", "$attack", "$defence", {
$devide: ["$endurance", 3]
}]
}
}
const result = await collection.updateOne(filter, updateDoc, options);
console.log(
`${result.matchedCount} document(s) matched the filter, updated ${result.modifiedCount} document(s)`,
);
} finally {
res.redirect('/main');
await client.close();
}
}
run().catch(console.dir);
})
Does anyone know how to fix this?
Upvotes: 0
Views: 120
Reputation: 4452
Update based on comment by @WernfriedDomscheit
if you are using MongoDB version > 4.2, then you can use pipeline inside update
So the update query like below:
db.users.updateOne({},
[
{
$set: {
attack: 1,
defence: 2,
endurance: 3
}
},
{
$set: {
power: {
"$add": ["$attack", "$defence", { $divide: ["$endurance", 3] }]
}
}
}
],
{ upsert: true }
);
will have the output:
{
"_id" : ObjectId("603124a22391a75d9a2ddec0"),
"attack" : 1,
"defence" : 2,
"endurance" : 3,
"power" : 4
}
So in your case:
const updateDoc = [
{
$set: {
health: 150,
attack: 3,
defence: 3,
endurance: 10,
characterimg: "https://i.ibb.co/MPg2SMp/Apocaliptic1.png",
}
},
{
$set: {
power: {
$add: ["$attack", "$defence", { $divide: ["$endurance", 3] }]
}
}
}
];
Upvotes: 1
Reputation: 59456
Try this one:
const updateDoc = [
{
$set: {
health: 150,
attack: 3,
defence: 3,
endurance: 10,
characterimg: "https://i.ibb.co/MPg2SMp/Apocaliptic1.png",
}
},
{
$set: {
result: { $sum: ["$power", "$attack", "$defence", { $divide: ["$endurance", 3] }] }
}
}
];
const result = await collection.updateOne(filter, updateDoc, options);
You need two $set
stages. Otherwise $sum: [...]
(or $add
) will use old values or fail if fields did not exist before. Also be aware that updateDoc
need to be an array, see updateOne()
Upvotes: 2