MongoDB NodeJS update removes attributes - node.js

When I'm trying to update a single attribute of a user's document after the update query every attribute of the user is missing except the _id and updated attribute. What's wrong with my query?
dbwrapper.mongo.getConnection().then(function(db){
db.collection('users').update({'_id' : dbwrapper.mongo.ObjID(userID)}, {'iconID':2}, function(error, resultMongo){
console.log(error);
if(error || !resultMongo){
reject(error);
}else{
resolve(resultMongo);
}
});
});

That's how updates work with MongoDB: if the second ("update") document contains only field:value expressions, the document stored in the database will be replaced by the update document. This is documented here.
If you merely want to update the iconID field, use $set:
.update({ '_id' : ... }, { $set : { iconID : 2 }}, ...)

Related

NodeJS MongoDb updateMany() with a condition?

I want to update a MongoDb collection with an Array of JSON objects.
However, I want the update to ignore any objects that already exist in the DB.
Sounds easy, but the key that allows me to know if the object exists is not the '_id', but a different 'id' (or other key).
Is that possible ?
Currently I am using it like this:
dbHandle.collection('contents').updateMany(contents);
where 'contents' is the Array of JSON objects.
Thanks in advance
The following operation updates all documents where violations are greater than 4 and $set a flag for review:
try {
db.restaurant.updateMany(
{ violations: { $gt: 4 } }, //Your Condition
{ $set: { "Review" : true } } //YOUR JSON contents
);
} catch (e) {
print(e);
}
Change the condition accordingly.

Update multiple documents and return all updated documents

I am looking for a way to update many documents at once using mongoose and return all the modified documents. I tried with setting multi:true in update(). It is updating all matching documents but not returning any. Then I tried with findOneAndUpdate(). It is updating and returning only one document even if there are many matching ones. Yeah, the function name itself tells, it will update only one, still I tried. I could not set option like multi:true in findOneAndUpdate(). How can it be done? Thanks in advance
Currently I don't think its possible in MongoDB to update multiple documents and return all the updated documents in the same query.
In Mongoose, the findOneAndUpdate() is based on the native findAndModify() method of MongoDB.
If you check the offical documentation of the findAndModify() method, its states that -
The findAndModify command modifies and returns a single document.
Although the query may match multiple documents, findAndModify will only select one document to modify.
Hence, you can not update multiple documents using findAndModify.
update() or updateMany() method on the other hand updates many documents with the multi flag but it only returns the WriteResult which looks like this -
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
I know, I'm too let, but I also face this same requirement as yours,
Here is what I apply in Controller to get the requirement done as yours by NodeJs...
export const updateManyData = async (req, res) => {
try {
const updateAllData = await Model.updateMany({} , {$set: {status: "active"}});
const sendToClient = await Model.find();
console.log(updateAllData); // => just updated status is here
console.log(sendToClient); // your all updated result is here
res.send('Update Many Post Successful!');
} catch (error) {
res.status(500).send('Server Side Error');
}
}
First upate and then get as per Jyotmans answer.
const update = await Model.updateMany({
condition: "value"
}, {
"$set": {
field: "value"
}
}, {
"multi": true
});
// res.json(icMessages)
const get = await Model.find({
room: req.params.room
}).exec()
res.json(get)

Not able to delete a field using findAndModify query

I am trying to update existing mongodb document using findAndModify query in node.js. I want to add product_category_ids field & remove error_state field. I want to do these two updates in single query. If I specify only $set it is working fine but if I specify both $set & $unset, it sets product_category_ids to null value.
my query is as follows:
conn.collection('error_import').findAndModify({_id:o_id},[['_id',1]],{ $set: {"product_category_ids":sss.category}}{ $unset: {"error_state":""}},{new:true},function(err,result) {
if ( err )
console.warn(err);
else {
conn.collection('product_import').insert({"tags":result.value.tags, "category_hierarchy":result.value.category_hierarchy, "error_state":result.value.error_state});
}
});
Please help me with this.Thanks in advance.
try using
{ $set: {"product_category_ids":sss.category}, $unset: {"error_state":""}}
instead of
{ $set: {"product_category_ids":sss.category}}{ $unset: {"error_state":""}}

Mongoose $push cannot push object into correct document

I have a mongoose schema like this:
A = {
_id: Schema.Types.ObjectId,
arrayA:[{
_id,
nestedArray: [Schema.Types.ObjectId]
}],
arrayB: [Schema.Types.ObjectId]
}
I would like to push an Object Id into nestedArray in specific arrayA object AND
arrayB should contains an specific Object Id by following code:
A.update({'arrayA._id': arrayAId, arrayB: {$in: [arrayContainsSomeArrayBIds]}},
{$push: {'arrayA.$.nestedArray': nestedArrayId}}, function(err) {
});
However, the Object Id is pushed into nestedArray of the last object in arrayA.
If arrayB: {$in: [arrayContainsSomeArrayBIds]} is removed, the Object Id can be pushed into correct object in arrayA.
mongoose version: 3.8.21
Can anyone help me to find out the problem?
Currently it is not possible in MongoDB to update an a array element with the positional operator, when the query document contains references to other arrays apart from the one being updated.
The below code, contains reference to two arrays fields: arrayA and arrayB, when
the update is issued on arrayA. This is invalid and would lead to undesired behavior.
A.update({'arrayA._id': arrayAId, arrayB: {$in: [arrayContainsSomeArrayBIds]}},
{$push: {'arrayA.$.nestedArray': nestedArrayId}}, function(err) {
});
From the docs,
Only one array field may appear in the query document.
The query document should only contain a single condition on the array field
being projected.
Multiple conditions may override each other
internally and lead to undefined behavior.
Under these requirements,
the following query is incorrect:
db.collection.find( { <array>: <value>, <someOtherArray>: <value2> },
{ "<array>.$": 1 } )
The solution is to modify your code to fire two queries:
Get the _ids of the documents, which match our condition.
Then perform the update.
Sample Code flow:
A.find({'arrayA._id': arrayAId, arrayB: {$in: [arrayContainsSomeArrayBIds]}},
function(err,data){
data.forEach(function(doc){
A.update({'arrayA._id': arrayAId,
"_id":doc._id},
{$push: {'arrayA.$.nestedArray': nestedArrayId}},
function(err) {
});
})
});

Node.js MongoDB Upsert update

I'm writing a little application which scores keywords. So if "beirut" and "education" get entered in, if they haven't been seen before, I want to create a mongo entry, and give them a score of 1. If they have, I want to increment their score by one. I'm trying to do this with one update command, but I think I might be doing it wrong.
Ranking is the object representing the database
"key" is the keyword
rankingdb.update(
{keyword:key},
{keyword:key, {$inc:{score:1}}},
{upsert:true, safe:false},
function(err, data) {
if (err) {
console.log(err);
}
else {
console.log("score succeeded");
}
}
);
SyntaxError: Unexpected token {
Can you not create a brand new document with an increment?
Your general approach is right, but as the error message suggests, you've got a syntax problem in your code.
Try this instead:
rankingdb.update(
{keyword: key},
{$inc: {score: 1}},
{upsert: true, safe: false},
function(err,data){
if (err){
console.log(err);
}else{
console.log("score succeded");
}
}
);
When an upsert needs to create a new object it combines the fields from the selector (first parameter) and the update object (second parameter) when creating the object so you don't need to include the keyword field in both.
Note that update() is deprecated in the 2.0 driver, so you should now use either updateOne() or updateMany().

Resources