I am finding any document that matches my condition and I want to remove those docs.
MyModle.find({writer: req.body.id}, function(err, docs){
if (err){ return console.log(err)}
if (!docs || !Array.isArray(docs) || docs.length === 0){
return console.log('no docs found')}
docs.forEach( function (doc) {
doc.remove();
console.log("Removed book with ID ",doc._id, "by writer ", req.body.id);
});
});
My console is printing the message as if the document was removed, but it is still in the collection.
What is wrong here?
As stated in the documentation for remove, the deletion is performed only if you either:
pass a callback function: doc.remove(function() { console.log('removed!'); });
or call exec: doc.remove().exec()
See also this question
To fix your code, you can replace:
doc.remove();
console.log("Removed book with ID ",doc._id, "by writer ", req.body.id)
with
doc.remove(function() {
console.log("Removed book with ID ",doc._id, "by writer ", req.body.id)
});
Related
How can I check if the remove-method of a Mongoose model really has removed something?
MyModel.remove({_id: myId}, function(err, entry) {
if(entry == null) next(new Error("ID was not found.")); // this doesn't work
}
Can I check how many documents were removed?
In the Mongo-Documentation kristina1 write in a comment:
If you call db.runCommand({getLastError:1}) after a remove and the "n" field will tell you how many documents were deleted.
But I don't know how to do this with Mongoose.
Mongoose < 4, MongoDB < 3
The second parameter to the remove callback is a number containing the number of documents removed.
MyModel.remove({_id: myId}, function(err, numberRemoved) {
if(numberRemoved === 0) next(new Error("ID was not found."));
}
Mongoose 4.x, MongoDB 3.x
The second parameter passed to the remove callback is now an object with the result.n field indicating the count of removed documents:
MyModel.remove({_id: myId}, function(err, obj) {
if(obj.result.n === 0) next(new Error("ID was not found."));
}
I tried this with latest version of mongoose, and it did not work. As the second parameter comes back as operation result, not just count. Used as below, it worked :
Model.remove({
myId: req.myId
}, function(err, removeResult) {
if (err) {
console.log(err);
}
if (removeResult.result.n == 0) {
console.log("Record not found");
}
Console.log("Deleted successfully.");
});
I stumbled upon this in 2020 and found with Mongoose 5.9.28 that the result no longer requires a result wrapper, so using remove to get a count of deleted records in an async method looks like:
async function remove(query) {
const result = await ItemModel.remove(query);
return result.n;
}
Of course, collection.remove is deprecated in favor of deleteOne or deleteMany, so try this as well.
First off, don't worry, it's a tiny data set - I realise it wouldn't be wise to dump an entire production DB to a single screen via an API... I just need to get a JSON dump of entire (small) DB to return via an API endpoint in a Node.js application.
My application does successfully return single records with this code:
MongoClient.connect("mongodb://localhost:27017/search", function (err, db) {
if(err) throw err;
db.collection('results', function(err, collection) {
// search for match that "begins with" searchterm
collection.findOne({'string':new RegExp('^' + searchterm, 'i')}, function(err, items){
// get result
var result;
if (items == null || items.result == null){
result = "";
}
else {
result = items.result;
}
// return result
res.send(result);
});
});
});
So I know Node is talking to Mongo successfully, but how can I tweak this query/code to basically return what you get when you execute the following on the MongoDB command line:
$ db.results.find()
This is snippet.
model.find({}).exec(function (err, result) {
if (err) {console.error(err); return;}
else return result;
});
First use your predefined model and call find. the logic is to place a empty object {} essentially rendering . select all from this model.
Make sense?
Exactly as you've described it.
collection.find({}).exec((err, result) => {
if (err) {
console.log(err);
return;
}
if (result.length > 0) {
// We check that the length is > 0 because using .find() will always
// return an array, even an empty one. So just checking if it exists
// will yield a false positive
res.send(result);
// Could also just use `return result;`
});
Thanks guys, I appreciate your answers pointing me in the right direction, in terms of using {} as the query. Here is the code that eventually worked for me:
db.collection('results', function(err, collection) {
collection.find({}).toArray(function(err, docs) {
res.send(docs);
});
});
The crucial element being the toArray(...) part.
I want to use the validation in my schema. Therefore i can't use findOneAndUpdate (?). I must use save.
Problem is, if I use findOne, then replaces the object with the one I'm going to replace it with, it will no longer have the save function.
mongoose.model('calculations').findOne({calcId:req.params['calcId']}, function(err, calculation){
if(err) {errHandler.serverErr(err, res, 'Something went wrong when trying to update a calculation'); return;}
calculation = calculationToReplace;
calculation.save(function(err, calc){ //No longer exists
if(err) {errHandler.serverErr(err, res, 'Something went wrong when trying to update a calculation'); return;}
res.send(200);
});
});
This must be a common task but I can't find any solution. How do I fix this?
There is a simple solution to your (by now really old) question.
In my case I had to have a findOneAndUpdate upsert that returned more information on what happened. So my solution was to step through the process to update the object with a for loop.
(Think the reason why you can't just copy is that the doc object contains a bunch of "extras" like version information and save function and other "bits"); So here is my solution.
exports.postData = function(req,res) {
console.log("will create " + req.body.alias);
console.log("It is level " + req.body.level); //OK, all this have to be changed to members of the data! req.body contains all the data sent from the user at this time
var query = { 'fulltext' : req.body.fulltext};
console.log("Checkking if " + req.body.fulltext + " exists")
Skill.findOne(query, function (err,doc){
if(err) return res.status(500).send(err)
if (!doc){
console.log(req.body.fulltext + " not found!")
var newdoc = new Skill(req.body);
newdoc.save(function(err){
if(err) return res.status(500).send(err)
console.log(newdoc.fulltext + " created as " + newdoc._id);
return res.status(200).send({_id: newdoc._id, alias: newdoc.alias})
})
return res.status(200).send('blal')
} else {
console.log(req.body.fulltext + " found!")
for (var id in req.body ){
doc[id]= req.body[id];
}
doc.save( function(err){
if(err) return res.status(500).send(err)
return res.status(200).send({_id: doc._id, alias: doc.alias})
})
//return res.status(200).send({_id: doc._id, alias: doc.alias})
}
I have not tested the following, so I am not sure if this works properly but it should probably be fine:
Swap this:
calculation = calculationToReplace;
with this:
for (var key in calculationToReplace)
if(typeof calculation[key] !== 'function')
calculation[key] = calculationToReplace[key];
Yes there is a way. You can read the mongoose documentation here. Take a look at the following code.
Tank.findById(id, function (err, tank) {
if (err) return handleError(err);
tank.size = 'large';
tank.save(function (err) {
if (err) return handleError(err);
res.send(tank);
});
});
This approach involves first retreiving the document from Mongo, then issuing an update command (triggered by calling save).
I am trying to save a new Document (user) in my MongoDb and I use callback. The code runs and goes until save the user, but after that I get an error.So I can save user. I have the following code:
function saveUser(userName, socialMediaType, socialMediaID, setDocNumber, callback){
var user;
if(socialMediaType == "fbUID"){
user = new users({
userName: userName,
userEmail: 'userEmail',
teams:[],
fbUID : socialMediaID
});
}else
if(socialMediaType =="google"){
//do the same
}
var query = {}
query["'"+ socialMediaType +"'" ] = socialMediaID
users.findOne(query, function(err, userFound){
if (err) { // err in query
log.d("Error in query FoundUser", err)
log.d("User Found", userFound)
}else
if(userFound == undefined){ //if user does not exist
user.save(function(err, user){
if(err) return console.error(err);
log.d("user saved", user);
currentSession = sessionOBJ.login(user._id, socialMediaID);
callback(currentSession,"created")
});
}else{
currentSession = sessionOBJ.login(userFound._id, socialMediaID);
callback(currentSession,"logged")
}
});
}
I call the function above through this code:
f(fbUID !== undefined){
userModelOBJ.saveUser(userName,"fbUID", fbUID, function(currentSession, status) {
res.send({"status":status,
"sessionID": currentSession.sessionID,
"expires" : currentSession.date});
});
I am getting this error :
The error is in the line :
callback(currentSession,"created")
What could be the problem?
I already did many researchers but this is a specific case.
Your saveUser() call is missing the setDocNumber argument. It looks like you're not using it in your code though, so you might be able to safely remove it. If you are using it somewhere else (that you haven't shown) then you need to do some argument checking at the top of saveUser() to support optional arguments.
I am attempting to break out of a function based on an expression, however am having trouble with the scoping. Here is a snippet of the code:
function createService(dict, res) {
// Ensure no duplicate
var serviceExists = Service.find({name: dict['name']}).count().exec(function(err, doc) {
return (doc !== 0);
});
console.log(serviceExists);
if(serviceExists){
res.send(500, "Duplicate document. Try updating existing entry or chooseing a different name");
return;
}
//Insert the document
service = new Service(dict);
service.save(function(err) {
if(!err) {
res.send("Service saved");
}
});
}
The output of the console.log():
{ emitted: {},
_events: { err: [Function], complete: [Function] } }
The end goal here is that the code will not reach the "Insert the document" portion if doc !== 0. Please let me know the correct way of doing this (Maybe using exceptions? That is the only idea I have left). Thanks
Service.find is asynchronous. the callback in exec doesn't execute immediately. This causes problem 1. (If Service....exec(...) returned a value, your console.log would have already excuted, before the callback.)
Problem 2 is also pretty common. return in exec() doesn't return a value you can assign to a variable. (exec() does not return the return value of your anonymous function.)
Here is a fix for your code:
function createService(dict, res) {
// Ensure no duplicate
Service.findOne({name: dict['name']}).count().exec(function(err, doc) {
var serviceExists = (doc !== 0);
console.log(serviceExists);
if(serviceExists){
res.send(500, "Duplicate document. Try updating existing entry or chooseing a different name");
return;
}
//Insert the document
service = new Service(dict);
service.save(function(err) {
if(!err) {
res.send("Service saved");
}
});
});
}
I also changed find to findOne, otherwise you'll get an array instead of a doc.