mongodb trying to drop a collection that might not exist - node.js

I'm getting:
(node:78465) UnhandledPromiseRejectionWarning: MongoError: ns not found
My code:
delete(projectId) {
if (!this.db) return
this.db.collection(projectId, (err, collection) => {
// err is null here.
collection.drop();
});
}
How do I make sure I don't get the error if the collection doesn't exist.

Use promises:
this.db.collection(projectId).drop().then(function () {
// success
}).catch(function () {
// error handling
})

So ns namespace error would come up when trying do something with a collection that does not exists. With your code you could do:
delete(projectId) {
if (!this.db) return;
this.db.collection(projectId).drop((err, dropOK) =>{
if (err) {
console.error("There is an error::", err);
return;
}
if (dropOK) console.log("Collection deleted");
});
}
Some points from understanding the problem:
db.colletion(anyString) would just return the interface with
anyString sitting inside the namespace & all the action definitions
that you might want to execute with that collection.
So with error first callback on db.collection(anyString, (e,res)) e will be null only and result would be passed to res as long as db is alive.
And that is why db.collection() itself is not an async function and the callback isn't really needed.
It is the action like collection.drop() that is async goes to drop it but doesn't find it and hence the error.
And drop() is the actual one that needs a callback with error to identify.

Related

Struggling with calling a function that uses promises in node.js

I am struggling with some code... The 2 examples below I would think would work the same but the second example throws an error? I am also struggling to figure out the error, it's not bubbling up? Admittedly I am not a seasoned node developer so any guidance would be much appreciated! If it's relevant the create method in the module is calling the sequelize create.
This works
var p1 = deliverabiltyConfigs.create2(cfgObject);
return Promise.all([p1]).then(function([res1]) {
res.json({result: res1})
});
This does not
deliverabiltyConfigs.create2(cfgObject).then(res1 =>{
res.json({result: res1})
})
Here is the function that I am calling in a controller module
exports.create2 = (dConfig) => {
DeliverabilityConfig.create(dConfig)
.then(data => {
return data
})
.catch(err => {
return {
message:
err.message || "Some error occurred while createing this config."
};
});
};
The create2 function always returns null, so neither invocation will work. Promise.all([p1]) hides the problem, returning a promise to perform an array of no promises.
create2(cfgObject).then(res1 =>{ attempts to invoke then() on null, generating a more obvious error. But neither way works.
Fix by deciding which promise syntax you want, using each as follows:
Using original promise syntax....
exports.create2 = dConfig => {
// note the return
return DeliverabilityConfig.create(dConfig)
.catch(err => {
const message = err.message || "Some error occurred while createing this config.";
return { message };
});
};
// caller
deliverabiltyConfigs.create2(cfgObject).then(result =>{
res.json(result);
})
With recent syntactic sugar...
exports.create2 = async (dConfig) => {
try {
// its fine to not await here, since the caller will await
// but just to illustrate how you might perform more async work here...
return await DeliverabilityConfig.create(dConfig);
} catch (err) {
const message = err.message || "Some error occurred while createing this config."
return { message }
}
}
// caller
var result = await deliverabiltyConfigs.create2(cfgObject);
res.json(result);
Use Promise.all() to run >1 promise concurrently. You've only got one promise in the OP, so no reason for it here.

FindOne in mongoose returns undefined

When im consoling all the data int he database using Find method, an object with Title:'day1' is present in it but when I perform findOne operation I get undefined as output.
Please help me.
Post.findOne({ Title: 'day1'}).then(function(err, result){console.log(result)});
Use the following query instead
Post.findOne({ Title: 'day1'},function(err,data)
{
if(err)
{ res.send(err)}
else if(data)
{res.send(data)}
})
It is because you mixed up callback with Promise..
If you will use Callback method you can use the following code:
Post.findOne({Title: 'day1'}, (err, data) {
if (err) {
return res.status(404).send(err); // If there is an error stop the function and throw an error
}
res.status(200).send(data) // If there is no error send the data
})
If you are going to use the promise method:
Post.findOne({Title: 'day1'})
.then(data => res.status(200).send(data)) // Send data if no errors
.catch(err => res.status(404).send(err)) // Throw an error if something happens

How to fetch by id from Firestore?

I have been trying so hard for a couple of hours but it seems so difficult for such a simple thing. i need to fetch by id from Firebase and here is the code that I am using but which is not working:
fetch_selected_restaurant = () => {
var ref = firebase.firestore().collection('restaurants').where("res_id", "==", "5").get();
}
Keep in mind that reading firestore/firebase database is an asynchronous operation.
If you want to read document by id, you have to call it like that:
var ref = firebase.firestore().collection('restaurants').doc(yourDocId).get()
If you remember, few lines above I mentioned that almost all operations with firestore are asynchronous, reading document is not an exception. After you call get() it returns Promise. I see you stored this promise in ref variable, that`s fine.
Now in order to get a result, you have to ask this promise for results. On this step you can get what you want:
ref.then(function(doc) {
if (doc.exists) {
console.log("Document data:", doc.data());
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
}).catch(function(error) {
console.log("Error getting document:", error);
});

How to check if a collection already exists in ArangoDB

Say I have a collection Col1 that already exists in my database. So, doing something like:
var col = db.collection('Col1');
col.save({"name":"something"});
will work perfectly fine.
But if a collection Col2 that doesn't already exist in my database is tried with the same thing i.e
var col = db.collection('Col2');
col.save({"name":"something"})
will work perfectly fine as well. Only that it doesn't exist and will be not shown in my database. Had it thrown some error or stuffs I could have used try and catch statements for result. But since that is off the plate, how do I know if a collection already exists ?
There are two things going on here that may be confusing.
First of all, arangojs (unlike the internal JS API of ArangoDB) is asynchronous for everything that needs to talk to the actual ArangoDB server. Asynchronous functions are marked as "async" in the documentation.
You can pass a node.js-style callback (like the async functions in built-in node.js modules, e.g. fs, http, etc) to these methods. Alternatively you can simply omit the callback and the method will return a promise for the result. You can learn more about how promises work in Mozilla's JavaScript reference documentation (this is not specific to Mozilla -- their reference is just very good and generally correct).
The other thing you're running into is the distinction between collection objects in arangojs and actual collections in ArangoDB. The driver lets you create collection objects for collections regardless of whether they exist yet or not. When trying to use them if the collection doesn't actually exist, you will of course see an error.
var col = db.collection('whatever');
col.create() // create the collection if it doesn't exist
.catch(function () {}) // ignore any errors
.then(function () {
return col.get(); // make sure the collection exists now
})
.then(function () {
return col.save({some: 'data'});
})
.then(function (result) {
// everything went fine
})
.catch(function (e) {
console.error('Something went wrong', e.stack);
});
Or using async/await (if you use Babel or read this answer one year from now):
var col = db.collection('whatever');
try {
await col.create(); // create the collection if it doesn't exist
} catch (e) {} // ignore any errors
try {
await col.get(); // make sure the collection exists now
const result = await col.save({some: 'data'});
// everything went fine
} catch (e) {
console.error('Something went wrong', e.stack);
}
Or using node.js-style callbacks because you're oldschool or really like pyramids:
var col = db.collection('whatever');
col.create(function () { // create the collection if it doesn't exist
// ignore any errors
col.get(function (err) { // make sure the collection exists now
if (err) {
console.error('Something went wrong', err.stack);
return;
}
col.save({some: 'data'}, function (err, result) {
if (err) {
console.error('Something went wrong', err.stack);
return;
}
// everything went fine
});
});
});
col.save does not execute the save operation immediately but returns a promise. So it will always succeed. The solution is to wait for the promise to be resolved and then react upon whether an error occurred or not:
var col = db.collection('Col2');
col.save({"name":"something"}).then(
meta => console.log('Document saved:', meta._rev),
err => { console.error('Failed to save document:', err.errorNum, err.response.body.errorMessage); }
);
https://docs.arangodb.com/3.1/Manual/DataModeling/Collections/DatabaseMethods.html#collection states
returns a single collection or null db._collection(collection-name)
so you can use
var col2 = db._collection('Col2');
if (col2) {
// collection exists
col2.save({"name":"something"});
}
This is old, but there is an exists() function.
Example in typescript/node
const metaResult = db.collection('myCollection');
if(!await metaResult.exists()) {
await db.createCollection('myCollection');
}

Testing Errors passed back with Callbacks with mocha and should

UPDATE 2-July-2013
Using the last approach with the wrapped anonymous function can introduce some strange testing behavior. If you expect a thrown error, but there is an error in the actual execution the test will pass, but will pass on any error and probably not the one you were expecting. I do two things, if its an error i am specifying i ensure the error text returned from the stub and the thrown error are the same. If it is from a third party library where i don't necessarily know the errors i will put some arbitrary value so that i know the passes are specific to the units i am testing. Example using sinon.js to stub some shizzle.
it('should return an error if the save fails', function(){
stubCall.restore();
stubCall = sinon.stub(Provider, 'save').callsArgWith(1, new Error('Save Error'));
(function(){
User.create(fakeUser, function(err, user){
if(err)
throw err;
});
}).should.throw("Save Error");
});
I am getting into Node.js and trying to do some Behaviour Driven Development(BDD) with Mocha and should.js (and sinon in there as well at some point).
One thing i am having problems with is testing errors returned by a call back, for instance this simple test:
it('should return an error if you try and execute an invalid Query object', function () {
var stubQuery = {};
Provider.execute(stubQuery, function (err) {
//should.not.exist(err);
should.have.property('message', 'Invalid Query Object');
});
});
with the function:
PostgresqlProvider.prototype.execute = function (query, cb) {
};
It doesn't matter what i try and test, the test always passes (should.exist, etc), and the only way i can get it to fail first is by adding cb(null); into the execute function, which kinda goes against what i am doing as i am trying to test before adding behaviour, not adding behaviour to fail a test.
I know i am doing some real newb mistake here, probably on a few levels but i am not grasping the testing of an error passed as a call back with is not thrown (which i am sure i could test easier)!
UPDATE
Using the code from Herman, i adjusted and that indeed words (the test is failing with no behavior defined)
it('should return an error if you try and execute an invalid Query object', function () {
var stubQuery = {};
Provider.execute(stubQuery, function (err) {
if (err) throw new Error(err);
}).should.throw();
});
issue now is i can't "catch" the error if sent in the callback to pass the test, the should.throw method doesn't get called, it just states that expected a throw to happen but didnt even though i am returning an error to the callback from my method. This could be down to scope
but i am unsure if i should add some form of closure, and at what level.
UPDATE 2
Figured it out, i needed to wrap the call to the function inside a closure, not the callback (Doh!) and then place the assert (should.throw) at the end of the closure;
it('should return an error if you try and execute an invalid Query object', function () {
var stubQuery = {};
(function(){
Provider.execute(stubQuery, function (err) {
if (err)
throw err;
});
}).should.throw();
});
You need to generate an exception inside your test function for the test to fail.
I'd add if (err) throw "Invalid query error " + err this way:
it('should return an error if you try and execute an invalid Query object', function () {
var stubQuery = {};
Provider.execute(stubQuery, function (err) {
if (err) throw "Invalid query error " + err
});
});
That should do.
(ON UPDATE)
should.throw() did not work for me either... I did this dirty hack to work the flow:
it('should return an error if you try and execute an invalid Query object', function () {
var stubQuery = {};
try {
Provider.execute(stubQuery, function (err) {
if (err) throw "Invalid query error " + err
});
// No error, keep on the flow
noError ();
} catch (e) {
// Error, let's continue the flow there
error (e)
}
function noError () {
// The flow in the event we have no error
// ... //
}
function error (errorObj) {
// The flow, in the event we have error
// ... //
}
});
Hope this helps!

Resources