mongoose callback is not an array - node.js

In my models I have this
module.exports.getPhotosById = function(userId,callback){
Photos.findOne({userId:userId},callback);
}
Then in route I do
Photo.getPhotosById(req.user._id,function(err,result){
console.log(result);
console.log(result.length);
});
The first console output this
{ _id: 325657865435643245,
userId: '32443564',
photo: 'abc.jpg',
caption: 'abc'
}
but why it's not an array? because the second console's output is undefined.

result is a single document instead of an array because you're calling findOne, not find.
To get all of a user's photo docs, change your method to:
module.exports.getPhotosById = function(userId, callback){
Photos.find({userId: userId}, callback);
}

findone Returns one document(JSON) that satisfies the specified query criteria
find Returns the array of Objects.

Related

Mongoose deleteMany using _id on nodejs

i have a ids of array ['123','456', '789']. i want delete all this array in mongodb
How i user it:
ScheduleModel.deleteOne({ _id: ['123','456', '789'] });
this is not working because this is not object Id
what i Need :
ScheduleModel.deleteOne({ _id: [ObjectId('123'), ObjectId('456'), ObjectId('789')] });
How to add object Id in array data. any how to resolve this issues. i need a solution on this.
It's not about ObjectId. you are using wrong syntax. You must use $in statement
ScheduleModel.deleteMany({ id: { $in: ['123','456','789'] } });
Use deleteMany with proper syntax.When there are many objectId at time Use $in.
Try this :
var deleteCondition = {
_id : {
//In Array you can pass your objectId
$in : ['123','456','789']
}
//You can pass other conditions
}
//deleteMany
ScheduleModel.deleteMany(deleteCondition, function (err, res) {
if (res) console.log(res)
})

nodeJS + MongoDB + Mongoose - Unable To Delete 1 Entry

I'm using nodeJS MongoDB/Mongoose to create/update/delete movies inside the database using Postman post/delete methods.
The create function is working fine, and even the remove function is working properly so when I use Postman I get the return: "Movie has been deleted!" like it should.
The only problem is that my function is emptying the entire database of movies instead of just that 1 movie, here is the remove function:
function destroy(req, res, next){
var movieID = req.body
Movie.remove(movieID, function(err,movie){
if(err){
res.status(400).send(err)
} else {
res.send("Movie has been deleted!")
db.close()
}
})
The movie object:
var movieSchema = new mongoose.Schema({
name: String,
yay: Number,
nay: Number,
release_date: Date,
in_theaters: Boolean,
released: Boolean,
buy_link: String,
imdb_link: String,
image_url: String,
description: String,
trailer_link: String
})
I want to delete a movie based on it's "name" so I only have to input the name and it will delete the entire movie.
Have you tried the findOneAndRemove query?
This query is much cleaner compared to finding a model and removing it inside the callback. Beside this I assume it's faster because you basically do 1 query instead of 2 after each other.
If you are passing direct value to Remove method, it will try to match with _id field.
As per your model, _id is ObjectId field which is managed automatically by mongodb.
In case if you enter like this. .remove("movie", callback) which is not a valid ObjectId.
Mongoose is discarding this invalid condition and executing Movie.remove({}); which is deleting all your records.
So it is better to validate whether the input is valid ObjectId or not before directly passing to Movie.remove();
I also recommend to use like this: Movie.remove({_id: movieId}, callback).
And for movie name :
Movie.remove({name: movieName}, callback);
Update:
You can take from Postman
var movieName = req.body.movieName;
Movie.remove({name: movieName}, function(err, updateObj){
});
Can you try this?
var movieName = req.body.name;
Movie.find('name': movieName, function(err, movie) {
if (err) res.send({error: err});
Movie.remove(function(err, movie){
if (err) res.send({error: err});
res.json({message: "Movie is removed", movie: movie});
});
});

Populate query in array nested documents - mongoose

My Output is in below image
and my populate query
Post.findOne({_id:req.query.id}).
populate('user').
populate('comment').
exec(function(err,docs){
if(err){
console.log(err);
}
console.log(docs);
res.send(docs);
});
});
How do I get user object data in comments array?
It used to be impossible with mongoose to populate fields of deeper populated objects directly in the query, but you could always use manual population by passing your resultdocs to the Comment.populate(comments, options, cb) method (http://mongoosejs.com/docs/api.html#model_Model.populate) inside your first callback.
With newer mongoose versions you should be able to do it directly using this syntax:
Post.
find().
populate({
path: 'comment',
populate: {
path: 'comments',
populate: 'user'
}
}
});

What is the difference between Model.findOne() & Model.findById() in Mongoose?

Consider we are searching a document from MongoDB based on the _id value. Which one of the following code is efficient ?
ModelObj.findById(IdValue).exec(callback);
ModelObj.findOne({ '_id': IdValue}).exec(callback);
I feel ModelObj.findById() is efficient, but what are the supportive reasons or How is it efficient?
findById is just a convenience function that does exactly the same thing as the findOne call you show.
Here's the source:
Model.findById = function findById (id, fields, options, callback) {
return this.findOne({ _id: id }, fields, options, callback);
};
findById(id) is almost equivalent to findOne({ _id: id }).
If you want to query by a document's _id, use findById() instead of findOne().
Both functions trigger findOne(), the only difference is how they treat undefined.
If you use findOne(), you'll see that findOne(undefined) and findOne({ _id: undefined }) are equivalent to findOne({}) and return arbitrary documents.
However, mongoose translates findById(undefined) into findOne({ _id: null }).
See https://mongoosejs.com/docs/api.html#model_Model.findById
Here's the source:
Model.findById = function findById(id, projection, options, callback) {
if (typeof id === 'undefined') {
id = null;
}
if (callback) {
callback = this.$wrapCallback(callback);
}
return this.findOne({_id: id}, projection, options, callback);
};
findById(id) is just syntactic sugar of the find({_id : id}) or findOne({_id: id})
Using .findOne makes the database look through its records checking each bson document to find the relevant variable and then check the value, if mongo knows its looking for the internally indexed _id field it doesn't have to look through each document

How to use mongoose findOne

I have the below schema (apologies that it is in coffeescript)
Schema = mongoose.Schema
AuthS = new Schema
auth: {type: String, unique: true}
nick: String
time: Date
Auth = mongoose.model 'Auth', AuthS
I simply want to recover one record which is definitely in my database:
Auth.findOne({nick: 'noname'}, function(obj) { console.log(obj); });
Unfortunately this always logs null. db.auths.findOne({nick: 'noname'}) in mongo shell always returns a value. What is going on?
Found the problem, need to use function(err,obj) instead:
Auth.findOne({nick: 'noname'}, function(err,obj) { console.log(obj); });
Mongoose basically wraps mongodb's api to give you a pseudo relational db api so queries are not going to be exactly like mongodb queries. Mongoose findOne query returns a query object, not a document. You can either use a callback as the solution suggests or as of v4+ findOne returns a thenable so you can use .then or await/async to retrieve the document.
// thenables
Auth.findOne({nick: 'noname'}).then(err, result) {console.log(result)};
Auth.findOne({nick: 'noname'}).then(function (doc) {console.log(doc)});
// To use a full fledge promise you will need to use .exec()
var auth = Auth.findOne({nick: 'noname'}).exec();
auth.then(function (doc) {console.log(doc)});
// async/await
async function async auth() {
const doc = await Auth.findOne({nick: 'noname'}).exec();
return doc;
}
auth();
See the docs if you would like to use a third party promise library.
In my case same error is there , I am using Asyanc / Await functions , for this needs to add AWAIT for findOne
Ex:const foundUser = User.findOne ({ "email" : req.body.email });
above , foundUser always contains Object value in both cases either user found or not because it's returning values before finishing findOne .
const foundUser = await User.findOne ({ "email" : req.body.email });
above , foundUser returns null if user is not there in collection with provided condition . If user found returns user document.
You might want to consider using console.log with the built-in "arguments" object:
console.log(arguments); // would have shown you [0] null, [1] yourResult
This will always output all of your arguments, no matter how many arguments you have.
Use obj[0].nick and you will get desired result,

Resources