Updating and Deleting documents using NodeJS on Cloudant DB - node.js

I was able to successfully query(select) and insert data into Cloudant database using HTTP /REST API. But I am not able to figure out - how to delete and modify documents.
For Delete: I tried the following code in nodejs
path : '/quick_loan_nosql_db_1?951b05d1b6aa100f4b94e5185674ef40/_rev=1-88963c755157188091f0d30115de18ce'
part of the REST API Request with METHOD: DELETE.
But when I execute it deletes the entire database instead of the ID being specified.
For Update: Can some one provide a sample, I tried with PUT, but in response I got a Conflict data error.
Any input would be appreciated.

Nice! To answer your original question, you just have the "/" and the "?" in the wrong places. To recap:
/quick_loan_nosql_db_1?951b05d1b6aa100f4b94e5185674ef40/_rev=1-88963c755157188091f0d30115de18ce
should instead be:
/quick_loan_nosql_db_1/951b05d1b6aa100f4b94e5185674ef40?_rev=1-88963c755157188091f0d30115de18ce

Here is one way I figured out to perform the Update and Delete.
I used nano api:
Include nano by
var nano =require('nano')('https://'+dbCredentials.user+':'+dbCredentials.password+'hostname:port/');
Please make sure to put the right user id and password
For Update
Update - you need to use insert api only, but with the right _id and _eval and the changes. For example:
nanodb.insert({ "_id": "3a1cc8c7f955f895131c3289f5144eab", "_rev": "2- 7040205a1c9270ad696724458399ac94", "name": "Tom", "employername":"Google"}, function(err, body, header) {
if (err) {
console.log('[db.insert] ', err);
return;
}
console.log('you have inserted the rabbit.')
console.log(body);
});
The above code will perform an update on the given id and the _rev. There will be a new revision number updated and the id will remain same. If you miss the ID or revision number, it will throw a conflict error.
For Delete
Simple use nano.destroy with the id and the revision number
nanodb.destroy("3a1cc8c7f955f895131c3289f5144eab","3-3e39e2298f109414cef1310449e0fd5c",function(err, body, header) {
if (err) {
console.log('[db.insert] ', err);
return;
}
console.log('you have inserted the rabbit.')
console.log(body);
});
Using Nano like framework API is better than making REST API calls over http for accessing the cloudant Database.
Hope this helps for people who want to connect to Cloudant db from NodeJS

Related

Nodejs, MongoDB concurrent request creates duplicate record

Let me be real simple. I am running node.js server. When I receive data from patch request, first I need to check in database. If the row exists I will update it, otherwise I will create that record. Here is my code. This is what I am calling in the request handler callback.
let dbCollection = db$master.collection('users');
createUser(req.body).then(user => {
dbCollection.updateMany(
{ rmisId: req.body.rmisId },
{ $set: { ...user } },
{ upsert: true }
).then((result) => {
log.debug("RESULTS", user);
return result;
})
.catch((err => {
log.debug(err);
return err;
}));
})
This is working fine in sequential requests. But its creating duplicate record when I receive 10 concurrent request. I am running on my local machine and replicating concurrent request using Apache JMeter. Please help me if you have experienced this kind of problem.
Thank you !
UPDATE
I have tested another approach that reads the database like dbCollection.find({rmisId: req.body.rmisId}) the database for determine its existing or no. But it has no difference at all.
You cannot check-and-update. Mongodb operations are atomic at the document level. After you check and see that the record does not exist, another request may create the document you just checked, and after that you can recreate the same record if you don't have unique indexes or if you're generating the IDs.
Instead, you can use upsert, as you're already doing, but without the create. It looks like you're getting the ID from the request, so simply search using that ID, and upsert the user record. That way if some other thread inserts it before you do, you'll update what the previous thread inserted. If this is not something you prefer, add a unique index for that user ID field.

Updating Particular field in Nodejs

I wanted to update the field data only ,but my code it adding an object each time i am calling update api.I have gone through many sites and found out updateOne is the method but couldnt end up undersatnding how to implement here.I am quite new to node so any help would be appreciated.
const update=(req,res)=>{
console.log(req);
models.detailsSchema.findByIdAndUpdate(req.body.vehicleId,req.body.data,{new:true}).then((msg,err)=>{
if(err)
res.status(400).json({err})
res.status(200).json({
"resCode":"0000",
"resStatus":"Success",
"resMsg":msg
})
});
}
Looks like you're using Mongoose connected to a MongoDB instance? If that's the case, Schema.findByIdAndUpdate works on the primary key or ObjectId of the record you're trying to update. To make this code work, if my assumptions are correct, change to this:
models.detailsSchema.findByIdAndUpdate(req.body._id, req.body.data, { new:true })
Of course, you're going to want to put in some check to make sure _id is defined if this is a create/update route.

Concurrentcy update in mongodb

I have used this code on node.js server side to update multiple embedded documents.
DetailerItemGroupModel.find({
"_id": itemGroupId
})
.forEach(function (doc) {
doc.Products.forEach(function (ch) {
//do something before update
});
DetailerItemGroupModel.save(doc);
});
I have the scenario like this :
Client A and B do GET http Method to get the same documents in the same time, then client B doing the update first(call to server which will run the code above) and then client A do the update.
So I want when client A's doing the UPDATE HTTP method to the server they must get the data which was latest (in this case is the document was updated by B) , I mean some how to cancel Client A request and return a bad request to tell the data Client A's going to update was changed by another client. Any way to implement that?
I read about "__v", but not sure when Client A and B send request to update same document at the same time, Does it work with forEach(), I change the code to this
DetailerItemGroupModel.find({
"_id": itemGroupId,
"__v" : {document version}
})
.forEach(function (doc) {
doc.Products.forEach(function (ch) {
//do some thing before update
});
DetailerItemGroupModel.save(doc);
});
The idea is that you want your "Save" to only work on the version that you have (which should be the latest).
Using .save will not help you here.
You can use one of two functions:
update.
findOneAndUpdate
The Idea is you have to do the find and save in one Atomic operation. And in the conditions object, you not only send the _id but you also send the __v which is the version identifier. (Something similar to the below example)
this.update({_id: document._id, __v: document.__v}, {$set: document, $inc: {__v: 1}}, result.cb(cb, function(updateResult) {
...
});
Say you read version 10, now you are ready to update it (save it). It will only work if it finds the document with the particular id and version. If in the meantime the database gets a newer version (version 11) then your update will fail.
BTW, MongoDb now has Transactions, you might want to look into that, because a transaction B would make your code wait until transaction A finishes it's atomic operation, which would be a better model than doing an update and failing and then trying again...

mongo db rest Api returns allways same entry

I am working on the development af a MEAN app and I have a curious problem:
I have created an API which allows me to get one single document by id:
//Get Single Line
router.get('/lines/:id', function(req, res, next){
db.lines.findOne(
{ _id: mongojs.ObjectId(req.params.id)},
function(err, line){
if(err){
res.send(err);
}
res.json(line);
});
});
Now when I call http://localhost:3000/api/lines/593379eb0cbd3a4efcdc1875 I get what I expect:
{"_id":"593379eb0cbd3a4efcdc1875","name":...
But, when I move this project to a live Server, when I call http://mydomain/api/lines/593379eb0cbd3a4efcdc1875 I allways get the first document in my collection:
{"_id":"59337c480cbd3a4efcdc1876","name":
Even if I try some id that does not exist - I allways get only the first document.
I really cant figure out, what the probem here is....
Did you try to debug the code to find whether correct _id passed to the controller and to the query? Recheck the database names and collection names matched with your repository for both local and live environments.

add an attachment to a document in couch db using nodejs

I want to update an existing document in couchdb. I have an image and i want to add it to an existing document in the db without lose the previus fields.
I'm using nodejs with nano.
tanks, this put me in the right orientation. At the end i do it in this way:
db.get(id,{ revs_info: true }, function (error, objeto) {
if(error)
console.log('wrong id');
fs.readFile('image.jpg', function(err, data)
{
if (!err)
{
db.attachment.insert(id, 'imagen.jpg', data, 'image/jpg',{ rev: objeto._rev}, function(err, body) {
if (!err)
console.log(body);
});
}
});
});
Your question is not really clear about the specific problem. So here just some general guidance on updating documents.
When designing the database make sure you set the ID rather than allowing couchdb to edit it. This way you can access the document directly when updating it.
When updating, you are required to prove that you are updating the most recent version of the document. I usually retrieve the document first and make sure you have the most recent '_rev' in the document you'll insert.
finally the update may fail if a different process has edited the document in the time between retrieving and updating it. So you should capture a failure in the insert and repeat the process until you succeed.
That being said, there are two ways you can store an image:
As an attachment: I believe nano support the attachment.insert() and attachment.get() functions to do so.
As a reference: I would usually rather store the images elsewhere and just store the url or filepath to access them. I've not used nano much but believe you can do this by doing the below.
doc = db.get(docname); // get the document with all existing elements
doc['mynewimage'] = myimageurl; // update the document with the new image
// this assumes it's a dictionary
db.insert(doc); // inserts the document with the correct _id (= docname)
// and _rev

Resources