So I am currently working on a project with mongodb and nodejs and I was wondering, how can you update data in mongodb via nodejs? My problem is that I want to keep the old data and add new. For example, here is the data currently in my mongodb
{
"_id" : ObjectId("5a1c0c1c3b147ec2e31cceb3"),
"event_id" : "1",
"event_medium" : "null",
"event_tags" : ["#JustTesting"]
}
So I want to add new data to the event_tags array and still keep the old data.
So for example the end result would be this:
{
"_id" : ObjectId("5a1c0c1c3b147ec2e31cceb3"),
"event_id" : "1",
"event_medium" : "null",
"event_tags" : ["#JustTesting", "#Test", "#Something"]
}
You should use the update function of MongoDB for that. MongoDB knows different update operators, in your case you may use $push or $pushAll (the second is deprecated):
update one after the other with $push
YourCollection.update({ _id: 'xxx' }, { $push: { event_tags: '#Test' } });
YourCollection.update({ _id: 'xxx' }, { $push: { event_tags: '#Something' } });
or both at once with $pushAll (deprecated now)
YourCollection.update({ _id: 'xxx' }, { $pushAll: { event_tags: ['#Test', '#Something'] } });
To interact with MongoDB form your NodeJS app, I would use a library like this one.
Your starting point is the Update function in CRUD (Create,Read, Update, Delete) operations in Mongodb.
Your node program should have among others the update function where you set the _id field you want to update and load the content fields to be update in 'data' for example as below:
myModel.prototype.update = function (_id, data, callback) {
const query = { _id: this.mongo.ObjectId(_id) };
debug(' update:' + JSON.stringify(query));
this.mongo.collection('mycollection').update(query, data, callback);
};
This piece of code should be put in your Model, if you use MVC pattern.
There is a lot to go.
Honestly I recommend a more deep tutorial like parts 3 and 4 of this one for nodejs and Mongoose (mongo db driver):
MDN tutorial for mongo/node/express
I assume you are using mongoose..
eventModel.findOne({event_id:1 },
function(err, eventObj){
if(err){
//handle error
} else {
if(eventObj === null) {
//event doesnot exist
}
var tagList = eventObj.event_tags;
tagList.push('new_tag1');
tagList.push('new_tag2');
eventObj.event_tags = tagList;
eventObj.save(function(err){
if(err){
//handle error
} else {
//success
}
})
Related
Hello how to update object field inside array of objects in MongoDB collection?
Structure of document is like this:
{
_id: ObjectId("60ebee6c2d610c17e4df2445")
languages: [ {code:"eng", word:"house", diff:23}, {code:"deu", word:"Hause", diff:6} ]
}
I tried with this query:
for (const sent of temparray) {
try {
Content.update({_id : sent.id , 'languages.code':'eng'} , { $set:
{
'languages.$.word' : sent.min.word
}
})
} catch (err) {
console.log('error updating document:', err)
}
}
I want to update field word in each eng sentence.
I'm using node js and express server.
But nothing happened any idea whats wrong?
I need to edit my prescriptions quantity .Here is my sample code.
collection.update(
{ "_id" : 1,"medications._id" : 23,"medications.prescriptions._id":77 },
{ $set : { "medications.$0.prescriptions.$1.quantity" : 30 } },
false,
true
)
How to edit this. It does not shown any error .
Instead you can follow a more easy to understand way.
var updateData = {
medications.prescriptions.quantity: 0
}
collection.update({ "_id" : 1,"medications._id" : 23,"medications.prescriptions._id":77 }, updateData, function(err, response){
if(err){
res.json(err);
}
//your success handler
});
you can use only one positional operator
And see this documentation:
https://docs.mongodb.com/manual/reference/operator/update/positional/
I have faced the same issue for the as array inside Array update require much performance impact. So, mongo db doest not support it. Redesign your database as shown in the given link below.
https://pythonolyk.wordpress.com/2016/01/17/mongodb-update-nested-array-using-positional-operator/
Node.JS, MONGODB, not using Mongoose.
I have a document I'm saving. When I use UPSERT, it structures the data as so :
{ "_id" : ObjectId("573a123f55e195b227e7a78d"),
"document" :
[ {"name" : "SomeName" } ]
}
When I use INSERT it inserts it all on the root level :
{ "_id" : ObjectId("573a123f55e195b227e7a78d"), "name" : "SomeName" }
This is obviously going to lead to lots of inconsistencies. I have tried various things. I've tried various methods such as findOneAndReplace, Update with Upsert, I've tried Replace, $setOnInsert. It all does the same thing when Upsert is involved it seems.
I have tried to use document[0] to access the first block of the array, but that throws an error... 'Unexpected Token ['
I have tried various methods and dug for hours through the various documentation, and have searched high and low for someone else having this problem, but it doesn't seem to be well documented issue for anyone else.
Anyone have any recommendations to make sure that all the fields are on the ROOT level, not nested under the variable name? Relevant code below.
findReplace: function(db, document, collection) {
var dbCollection = db.collection(collection);
var filter = document.name;
return new Promise(function(resolve, reject) {
dbCollection.updateOne({
"name" : filter
}, {
document
}, {
upsert: true
}, function(err, result) {
if (err) {
console.log('error', err)
reject(err);
}
console.log("Found Document and Upserted replacement Document");
resolve([{'status' : 'success'}]);
});
});
}
When you do this:
{
document
}
You are creating an object containing a document property and the variable's value as its value:
{
document: [ {"name" : "SomeName" } ]
}
This is new functionality from ES6. If you want to access the first item of the document variable, don't create a new object:
return new Promise(function(resolve, reject) {
dbCollection.updateOne({
"name" : filter
}, document[0], { // <========
upsert: true
}, function(err, result) {
if (err) {
console.log('error', err)
reject(err);
}
console.log("Found Document and Upserted replacement Document");
resolve([{'status' : 'success'}]);
});
});
I'm trying to:
Find a document according to a search criteria,
If found, update some attributes
If not insert a document with some attributes.
I'm using a Bulk.unOrderedOperation as I'm also performing a single insert. And I want to do everything in one operation againast DB.
However something it's causing nothing is being inserted for the update/upsert operation.
This is the insert document:
var lineUpPointsRoundRecord = {
lineupId: lineup.id, // String
totalPoints: roundPoints, // Number
teamId: lineup.team, // String
teamName: home.team.name, // String
userId: home.iduser, // String
userName: home.user.name, // String
round: lineup.matchDate.round, // Number
date: new Date()
}
This is the upsert document:
var lineUpPointsGeneralRecord = {
teamId: lineup.team, // String
teamName: home.team.name, // String
userId: home.iduser, // String
userName: home.user.name, // String
round: 0,
signupPoints: home.signupPoints, // String
lfPoints: roundPoints+home.signupPoints, // Number
roundPoints: [roundPoints] // Number
};
This is how I'm trying to upsert/update:
var batch = collection.initializeUnorderedBulkOp();
batch.insert(lineUpPointsRoundRecord);
batch.find({team: lineUpPointsRoundRecord.teamId, round: 0}).
upsert().
update({
$setOnInsert: lineUpPointsGeneralRecord,
$inc: {lfPoints: roundPoints},
$push: {roundPoints: roundPoints}
});
batch.execute(function (err, result) {
return cb(err,result);
});
Why wouldn't it be upserting/updating?
Note
That is JS code using waterline ORM which also uses mongodb native driver.
Your syntax here is basically correct, but your general execution was wrong and you should have "seperated" the "upsert" action from the other modifications. These will otherwise "clash" and produce an error when an "upsert" occurs:
LineupPointsRecord.native(function (err,collection) {
var bulk = collection.initializeOrderedBulkOp();
// Match and update only. Do not attempt upsert
bulk.find({
"teamId": lineUpPointsGeneralRecord.teamId,
"round": 0
}).updateOne({
"$inc": { "lfPoints": roundPoints },
"$push": { "roundPoints": roundPoints }
});
// Attempt upsert with $setOnInsert only
bulk.find({
"teamId": lineUpPointsGeneralRecord.teamId,
"round": 0
}).upsert().updateOne({
"$setOnInsert": lineUpPointsGeneralRecord
});
bulk.execute(function (err,updateResult) {
sails.log.debug(err,updateResult);
});
});
Make sure your sails-mongo is a latest version supporting the Bulk operations properly be the inclusion of a recent node native driver. The most recent supports the v2 driver, which is fine for this.
I recommend use bulkWrite exemplary code with bulk upsert of many documents:
In this case you will create documents with unique md5. If document exists then will be updated but no new document is created like in classical insertMany.
const collection = context.services.get("mongodb-atlas").db("master").collection("fb_posts");
return collection.bulkWrite(
posts.map(p => {
return { updateOne:
{
filter: { md5: p.md5 },
update: {$set: p},
upsert : true
}
}
}
),
{ ordered : false }
);
https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/
Typically I have always set upsert as a property on update. Also update should be able to find the record itself so no need to find it individually.
Depending on the environment the $ may or may not be necessary.
batch.update(
{team: lineUpPointsRoundRecord.teamId, round: 0},
{
$setOnInsert: lineUpPointsGeneralRecord,
$inc: {lfPoints: roundPoints},
$push: {roundPoints: roundPoints},
$upsert: true
});
I have the following update MongoDB query, run in Node.js via MongoDB native client. The query works correctly - I see objects being modified in my MongoDB after I run this code:
collection.update(
{
_id : request.query.person,
},
{
$inc: {
score : 1
}
},
{ safe : true},
this /* "this" is for Step */
);
I would like to know what is the number of records that were updated in MongoDB after my query. I have seen that I can do check it by running getLastError in MongoDB, but I am not sure how to do it from Node.js using the native client.
Any hints how to do it? Is there any other way than calling getLastError?
The second parameter to the update callback is the count of affected docs:
collection.update(
{ _id : request.query.person },
{ $inc: { score : 1 }},
{ safe : true},
function (err, numAffected) {
...
}
);
Update for the 2.x version of the native driver:
The second parameter to the update callback is now a nested object, where the number of documents updated can be found in result.nModified. But update is now deprecated so updateOne should be used instead.
collection.updateOne(
{ _id : request.query.person },
{ $inc: { score : 1 }},
{ safe : true},
function (err, response) {
console.log(response.result.nModified);
// Also available at response.modifiedCount for updateOne, but not update
console.log(response.modifiedCount);
}
);
The documentation for the 2.x callback parameters can be found here.