Why deleteOne & findById of mongoose work on deleted id - javascript

Currently developing an API with nodejs that communicates with a MongoDB database, I noticed a special behavior after deleting a document.
Indeed, my API has several endpoints that allow to retrieve all the animals in the database, to retrieve a specific one using the corresponding id or to delete a specific one, again using the id of the document to delete.
The results I don't understand happen once a document is deleted. Indeed, as you can see in the picture below, when I delete the document of the animal called "Johnny" the queries to find it via its id or to delete it via the same ID continue to work, even if the get returns nothing and the deletion indicates that no operation has been performed.
Personally I expected the same behavior as if I passed a wrong id for a deletion (visible below), but if the id has already been assigned in the database the queries work even after a deletion.
Does MongoDB have a "cache" of deleted documents in order to perform a rollback in case of unwanted deletion?
You will find below the different endpoints that use find, deleteOne & findById
exports.getAllAnimal = (req, res, next) => {
Animal.find().sort({'customer' : 1})
.then(animals => res.status(200).send(animals))
.catch(error => res.status(400).send({ error: error.message }));
};
exports.getOneAnimal = (req, res, next) => {
Animal.findOne({ _id: req.params.id })
.then(animal => res.status(200).send(animal))
.catch(error => res.status(400).send({ error: error.message }));
};
exports.deleteAnimal = (req, res, next) => {
Animal.deleteOne({ _id: req.params.id })
.then(thing => res.status(200).send({ message : 'Animal successfully deleted'}))
.catch(error => res.status(400).send({ error: error.message }));
};

MongoDB does not cache deleted id anywhere.
The thing is that when you said I passed a wrong id for a deletion ... you are passing an id with the same length but not in the required format. That's why Mongoose is throwing you an error.
However, if you follow the id structure of MongoDB to create an id that does not exist in the database and run an operation against it, MongoDB will still return you with success and an empty result.
Try using 5ea08034385a46666b05020f and run the .findById() query function against it. It's going to return you with a success an empty result.
The success only means that the operation is successful, but it doesn't necessarily mean that it actually finds something in the database.
I don't have access to your database, so the id is generated randomly but following the MongoDB ObjectId rules below:
The 12-byte ObjectId value consists of:
a 4-byte timestamp value, representing the ObjectId’s creation, measured in
seconds since the Unix epoch
a 5-byte random value
a 3-byte incrementing counter, initialized to a random value
Generate arbitrary MongoDB ObjectId:
https://observablehq.com/#hugodf/mongodb-objectid-generator

Related

Cosmos DB overwrite existing documents

Currently, I have this, which works fine.
this.container.items
.create<Session>(data)
.then(() => callback(null))
.catch((error) => {
console.log("error >>>", error)
callback(error)
});
However, if I try to create another document with the same ID, I get the error:
message: 'Entity with the specified id already exists in the system.
Is it possible to make Cosmos ignore it and overwrite the document, or is there a method on the NodeJS SDK for that?
You would need to use Upsert if you want to upadate the entire document , if you need to change few fields then consider using Patch operation
Upsert
const { resource: upsertedPerson1 } = await container.items.upsert(upsertSource);
Patch
const { resource: patchSource1 } = await container.item(patchId!).patch(replaceOperation);
Check the samples here.
You can use UPSERT method of items.
https://learn.microsoft.com/en-us/javascript/api/#azure/cosmos/items?view=azure-node-latest##azure-cosmos-items-upsert-1

TypeError: Cannot read property '0' of undefined in post method in nodejs

I am new to nodejs and mongodb.
I am trying to create simple to-do app with nodejs and mongodb.
I have added the task in database.
Now in post method, I am using insertOne method of mongodb and in res.json I am having the following error.
res.json(info.ops[0].data)
TypeError: Cannot read property '0' of undefined
Code :
app.post('/create-item', function(req, res){
db.collection('items').insertOne({ text:req.body.text }, function(err, info){
res.json(info.ops[0])
})
})
Below is the screenshot of Error.
In current versions, there is no property returned named ops when insertOne is successful.
Hence the error TypeError: Cannot read property '0' of undefined
insertOne returns two properties:
acknowledged
Indicates whether this write result was acknowledged. If not, then all other members of this result will be undefined
insertedId
The identifier that was inserted. If the server generated the identifier, this value will be null as the driver does not have access to that data
See:
InsertOne
InsertOneResult
app.post('/create-item', function(req, res){
db.collection('items').insertOne({ text:req.body.text }, function(err, info){
console.log(info.acknowledged)
console.log(info.acknowledged)
res.json(info.acknowledged)
})
})
In previous versions, for example 3.2, different properties were returned for insertOne:
insertOne #3.2
insertOneWriteOpCallback #3.2
Similarly, different properties were returned for updateOne:
updateOne #3.2
updateOneWriteOpCallback #3.2
For more information about migrating to version 4 from earlier versions, see the article:
Changes in 4.x (and how to migrate!)
I encountered the same problem with the to-do app tutorial today. For those interested try changing the line - res.json(info.ops[0])
to - res.json({ _id: info.insertedId.toString(), text: req.body.text })
This gets the inserted id from the database for the newly added item. As "info" doesn't seem to return the inserted text in the current version of mongodb - i added that from the request parameter.
I got my information from here - Get the _id of inserted document in Mongo database in NodeJS
you are doing it wrong way firstly check the err then send the res.json because the error is because your info might be null if data not inserted successfully so you need to do it like
app.post('/create-item', function(req, res){
db.collection('items').insertOne({ text:req.body.text }, function(err, info){
if (err) {
res.json({message: "not inserted successFully"});
return;
}
res.json(info.ops[0])
})
})
now in above code what will happen if data is not inserted successfully it will send the error as response and return from function.

Firebase Auth: updateProfile in Cloud Function?

I tried to use updateProfile() in my Cloud Function, triggered by HTTPS.
Error:
user.updateProfile is not a function
Cloud Function:
app.get("/user/create", (req, res) => {
res.setHeader('Content-Type', 'application/json')
admin.auth().verifyIdToken(req.query.token).then(user => {
let name = req.query.name
user.updateProfile({
displayName: name
}).then(() => {
res.send(JSON.stringify({
result: false,
error: err.message
}))
})
})
})
The error makes totally sense to me, but I've no clue how I can get a actual user reference to update the profile, any idea?
It looks like you're assuming that verifyIdToken() generates a promise that contains a User object. That's not the case here. According to the API docs, it provides a DecodedIdToken object. That object contains a uid property with the UID of the user represented by the token you passed to it.
If you want to get a UserRecord object from there, you can call admin.auth().getUser(uid) with that UID. However, that won't help you update the user's profile.
If you want to update the profile for a given UID, you can call admin.auth().updateUser(uid, properties).

How to update record in mongoose with nodejs?

I am trying to update a record in mlab, a remote mongodb database. I am using express, mongoose and nodejs to update a certain record. I also use promises to avoid the callback pyramid.
Api file:
router.put('/chairs/:id', function(req, res, next){
Chair.findByIdAndUpdate({id:req.params.id}, req.body)
.then(function() {
Chair.findOne({id:req.params.id})
})
.then(function(chair){
res.send(chair);
})
.catch(next);
});
I tested the code above using Postman 'x-www-form-urlencoded'. When i try to UPDATE just 1 field 'title' and send PUT REQUEST , I am prompted with
{
"myError": "Cast to ObjectId failed for value \"{ id: '5953532df36d28458af5609f' }\" at path \"_id\" for model \"chair\""
}
I want to update a record and get the ID again and print the updated record.
Please help. I am not sure how to properly nest my promises

node.js mongojs findOne callback returning error as null

Presently being driven up the wall by this error.
I am running a node.js app with the mongojs wrapper for mongodb. I Started mongod on the default port, then ran
var db = require('mongojs').connect('localhost:27017/my_db');
var users = db.collection('users');
users.findOne({'fb_id' : fbUserMetadata.id}, function(err, user) {
console.log(err);
console.log(user);
debugger;
});
however err and user are both 'null'. To my knowledge, err should be populated with some kind of data even if it doesn't find anything.
How do I get the callback function to work properly? Pardon the newbie question.
When the findOne query doesn't find at least one matching document, the second parameter of the callback (in this case user) is set to null. It's not an error, so err is also null. So what you're seeing is the expected no-match-found response.
Update
Note that findOne has been deprecated in the 2.0 driver, but its replacement also exhibits this same behavior:
users.find({'fb_id' : fbUserMetadata.id}).limit(1).next(err, doc) {
// doc is null if a matching document wasn't found
});

Categories