MongoDB/Mongoose returning empty array - node.js

I'm currently working on a project with mongodb/mongoose, and every time I purposely query for something that does not exist in the DB, I am getting a response with an empty array. This is my code for using Express to set up an API and return the data found in the DB:
app.get('/api/:id', function(req, res) {
var id = req.params.id;
Job.find({jobID: id}, function (err, foundJob) {
if (err) {
console.log(err);
}
else {
res.json(foundJob);
}
});
});
However, every time I go to localhost:3000/api/67 (I have no object with jobID: 67 in the database yet), the console does not print the error. It gives me a JSON response with an empty array. Any ideas to why this is happening? The weird part is that when I change jobID: id to _id: id, it does give me an error. Why doesn't it do that for the jobID field?
EDIT: Just to clarify, the reason why I do not want this behavior is because my program will never print the error, even if a job in my DB doesn't exist with that specified jobID.

It does something different than you think it does.
Job.find({jobID: id}, ... )
What this really says is give me array with all the documents in collection "Job" that have field "jobID" equal to some value.
What if there is no such document? Well, then the array will be empty. Without any error, of course, what should be an error here? You asked for all documents (given some filter) and an array with all such documents was returned. It is just a coincidence that the size of the array is zero, because there are no such documents.
If you want to check whether there is no such document then check whether the array is empty.
I don't know why it is giving you error when you change JobID to _id; what error exactly is it?
If you are interested only in one document, then there is method findOne that returns only the first document (or null if no such documents exist) instead of an array.

About error when you try to find something by it's __id: It gives you a error because __id is not String, it's ObjectId. So you should search for document with that __id like this: _id: ObjectId(id)
About empty string: If you want to display some kind of different message you should check if db returned something or is it rather empty string that got returned. Something like this:
app.get('/api/:id', function(req, res) {
var id = req.params.id;
Job.find({jobID: id}, function (err, foundJob) {
if(foundJob){
res.json(foundJob);
}else{
res.json("nothing found");
}
if (err) {
console.log(err);
}
});
});
Edit: I didnt realize that you had check for error, I changed code.

Returning an empty string is normal behavior for mongoose. You should handle your response like this:
if (err) {
//handle error
} else if (foundJob) {
//work with your data
} else {
//nothing was found
}
The error you get with _id must be irrelevant and is probably due to an invalid query.

Related

mongooseJS find returning all rows

On using mongoose find with a condition such as
var condition= $and:[{'Credentials.UserName' : 'param.uName'},
{'Credentials.Password' : 'param.Pwd'}]
Here param.uName and param.Pwd are actual values entered by the user, which is set within inverted comma programatically.
Its returning all records in the mongodb table.
On using
.findOne({condition},schema,(err,data){
res.send(data)
})
It always returns the first row everytime.
I am sure that am missing something. Where is it/What is it?
Am new to mongoose. Thanks in Advance.
Edward
you can try something like:
mongooseObject.find({condition}, function(err, data) {
if (err)
handle the error
else {
data should be an array of all matches
}
});

findOneAndUpdate works part of the time. MEAN stack

I'm working with the mean stack I'm trying to update the following object:
{
_id : "the id",
fields to be updated....
}
This is the function that does the updating:
function updateById(_id, update, opts){
var deferred = Q.defer();
var validId = new RegExp("^[0-9a-fA-F]{24}$");
if(!validId.test(_id)){
deferred.reject({error: 'invalid id'});
} else {
collection.findOneAndUpdate({"_id": new ObjectID(_id)}, update, opts)
.then(function(result){
deferred.resolve(result);
},
function(err){
deferred.reject(err);
});
}
return deferred.promise;
}
This works with some of my objects, but doesn't work with others.
This is what is returned when it fails to update:
{
ok: 1,
value:null
}
When the function is successful in updating the object it returns this:
{
lastErrorObject: {}
ok: 1
value: {}
}
It seems like Mongo is unable to find the objects I'm trying to update when it fails. However, I can locate those objects within the Mongo shell using their _id.
Does anybody know why the driver would be behaving this way? Could my data have become corrupt?
Cheers!
I found the answer and now this question seems more ambiguous so I apologize if it was confusing.
The reason I was able to find some of the documents using ObjectID(_id) was because I had manually generated some _id fields using strings.
Now I feel like an idiot but, instead of deleting this question I decided to post the answer just in case someone is running into a similar issue. If you save an _id as a string querying the collection with the _id field changes.
querying collection with MongoDB generated _ids:
collection.findOneAndUpdate({"_id": new ObjectID(_id)}, update, opts)
querying collection with manually generated _ids:
collection.findOneAndUpdate({"_id": _id}, update, opts)
In the second example _id is a string.
Hope this helps someone!

Why can't I seem to merge a normal Object into a Mongo Document?

I have a data feed from a 3rd party server that I am pulling in and converting to JSON. The data feed will never have my mongoDB's auto-generated _ids in it, but there is a unique identifier called vehicle_id.
The function below is what is handling taking the data-feed generated json object fresh_event_obj and copying its values into a mongo document if there is a mongo document with the same vehicle_id.
function update_vehicle(fresh_event_obj) {
console.log("Updating Vehicle " + fresh_event_obj.vehicleID + "...");
Vehicle.find({ vehicleID: fresh_event_obj.vehicleID }, function (err, event_obj) {
if (err) {
handle_error(err);
} else {
var updated = _.merge(event_obj[0], fresh_event_obj);
updated.save(function (err) {
if (err) {
handle_error(err)
} else {
console.log("Vehicle Updated");
}
});
}
});
}
The structures of event_obj[0] and fresh_event_obj are identical, except that event_obj[0] has _id and __v while the "normal" object doesn't.
When I run _.merge on these two, or even my own recursive function that just copies values from the latter to the former, nothing in the updated object is different from the event_obj[0], despite fresh_event_obj having all new values.
Does anyone have any idea what I'm doing wrong? I feel it is obvious and I'm just failing to see it.
The problem is that if you don't have properties defined in your schema, and if they don't already exist, you can't create them with
doc.prop = value
even if you have {strict:false} in your schema.
The only way to set new properties is to do
doc.set('prop', value)
(You still have to have {strict:false} in your schema if that property doesn't exist in your schema)
As for having too many properties to be defined in schema, you can always use for-in loop to go through object properties
for(key in fresh_event_obj)
event_obj.set(key, fresh_event_obj[key]);

Saving subdocuments with mongoose

I have this:
exports.deleteSlide = function(data,callback){
customers.findOne(data.query,{'files.$':1},function(err,data2){
if(data2){
console.log(data2.files[0]);
data2.files[0].slides.splice((data.slide-1),1);
data2.files[0].markModified('slides');
data2.save(function(err,product,numberAffected){
if(numberAffected==1){
console.log("manifest saved");
var back={success:true};
console.log(product.files[0]);
callback(back);
return;
}
});
}
});
}
I get the "manifest saved" message and a callback with success being true.
When I do the console.log when I first find the data, and compare it with the console.log after I save the data, it looks like what I expect. I don't get any errors.
However, when I look at the database after running this code, it looks like nothing was ever changed. The element that I should have deleted, still appears?
What's wrong here?
EDIT:
For my query, I do {'name':'some string','files.name':'some string'}, and if the object is found, I get an array of files with one object in it.
I guess this is a subdoc.
I've looked around and it says the rules for saving subdocs are different than saving the entire collection, or rather, the subdocs are only applied when the root object is saved.
I've been going around this by grabbing the entire root object, then I do loops to find the actual subdoc I that I want, and after I manipulate that, I save the whole object.
Can I avoid doing this?
I'd probably just switch to using native drivers for this query as it is much simpler. (For that matter, I recently dropped mongoose on my primary project and am happy with the speed improvements.)
You can find documentation on getting access to the native collection elsewhere.
Following advice here:
https://stackoverflow.com/a/4588909/68567
customersNative.update(data.query, {$unset : {"slides.1" : 1 }}, function(err){
if(err) { return callback(err); }
customersNative.findAndModify(data.query, [],
{$pull: {'slides' : null } }, {safe: true, 'new' : true}, function(err, updated) {
//'updated' has new object
} );
});

MongoDB Query returning false results

I have streamlined this question for simplicity. Value is passed to the function, and if there is no document with {field1: value}, create that document; otherwise, call another function. However, this query will always find a document, or perhaps fires whatever_function() regardless. Why can I not get (!doc) to be true? This database is operative and queries/updates appropriately except for this issue.
db.doc.find({field1: value}, function(err, doc) {
if (!doc) {
db.doc.save({field1: value});
}
else {
whatever_function();
}
});
Find returns a cursor to the selected documents. Then, you should check that doc length is 0.

Resources