How to check if a collection already exists in ArangoDB - node.js

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');
}

Related

Mongoose async/ await correct method

I'm new to mongoose and node could anyone please point out which is the right method, my intention is to send the list of all products in my MongoDB to client.
method 1
items = await Product.findById({})
.then((items) => {
if (items == null) {
res.status(404).send("no items");
} else {
res.send(items);
next();
}
})
.catch((err) => {
res.status(404).send({ error: err });
});
method 2
items = await Product.find({}).exec();
res.status(200).send(items)
next();
Also could you point out how can i use again one more await call if i have to process items and send after that.Thanks in advance.
Method 2 should looks like that:
router.get('/:param', async function(req, res) {
try {
let items = await Product.find({}).lean()
res.status(200).json(items);
} catch (e) {
res.status(404).json(e);
}
});
You don't need .exec()
You need to use .lean() if you want to receive js object in items, not mongoose's.
Try not to request all docs collection at once, especially if collection have more then 1000+ documents. Otherwise do it via .cursor or limit(Number) to avoid problems with DB.
Also as already mentioned above, try to use async/await and ES6 syntax. It's just looks better.
And please, mark question as answered, just to avoid your question to be flagged.

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);
});

mongodb trying to drop a collection that might not exist

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.

Recover an object requested with MongoDB Driver on node JS

I try to recover object from a mongo DB database, in a node JS file and it doesn't work.
In a file called db.js , i have made the following code :
var MongoClient = require('mongodb').MongoClient;
module.exports = {
FindinColADSL: function() {
return MongoClient.connect("mongodb://localhost/sdb").then(function(db) {
var collection = db.collection('scollection');
return collection.find({"type" : "ADSL"}).toArray();
}).then(function(items) {
return items;
});
}
};
And, I try to use it in the file server.js :
var db = require(__dirname+'/model/db.js');
var collection = db.FindinColADSL().then(function(items) {
return items;
}, function(err) {
console.error('The promise was rejected', err, err.stack);
});
console.log(collection);
In the result I have "Promise { }". Why ?
I just want to obtain an object from the database in order to manipulate it in the others functions situated in the server.js file.
Then then function called on promises returns a promise. If a value is returned within a promise, the object the promise evaluates to is another promise which resolves to the value returned. Take a look at this question for a full explanation of how it works.
If you want to verify that your code is successfully getting the items, you will have to restructure your code to account for the structure of promises.
var db = require(__dirname+'/model/db.js');
var collection = db.FindinColADSL().then(function(items) {
console.log(items);
return items;
}, function(err) {
console.error('The promise was rejected', err, err.stack);
});
That should log your items after they are retrieved from the database.
Promises work this way to make working asynchronously more simple. If you put more code below your collection code, it would run at the same time as your database code. If you have other functions within your server.js file, you should be able to call them from within the body of your promises.
As a rule, remember a promise will always return a promise.
The callback functions created in the then() are asynchronous, thus making the console.log command execute before the promise is even resolved. Try placing it inside the callback function instead like below:
var collection = db.FindinColADSL().then(function(items) {
console.log(items)
return items;
}, function(err) {
console.error('The promise was rejected', err, err.stack);
});
Or, for the sake of another example using the logger functions themselves as the callbacks, and showing that the last console.log call will actually be called before the others.
db.findinColADSL()
.then(console.log)
.catch(console.error)
console.log('This function is triggered FIRST')

Using Mongoose promises to do find and update

I'm trying to using the Mongoose Promises to have a cleaner code (see nested functions).
Specifically, I'm trying to build something like this:
Model.findOne({_id: req.params.id, client: req.credentials.clientId}).exec()
.then(function(resource){
if (!resource) {
throw new restify.ResourceNotFoundError();
}
return resource;
})
.then(function(resource) {
resource.name = req.body.name;
return resource.save; <-- not correct!
})
.then(null, function(err) {
//handle errors here
});
So, in one of the promises I would need to save my model. As of the latest stable release, Model.save() does not return a promise (bug is here).
To use the classical save method, I could use this:
//..before as above
.then(function(resource) {
resource.name = req.body.name;
resource.save(function(err) {
if (err)
throw new Error();
//how do I return OK to the parent promise?
});
})
But as also commented in the code, how do I return to the holding promise the return value of the save callback (which runs async)?
Is there a better way?
(btw, findOneAndUpdate is a no-go solution for my case)
One way of doing it would be to wrap the .save code in your own method which returns a promise. You'll need a promise library, like RSVP or Q. I'll write it in RSVP, but you should get the idea.
var save = function(resource) {
return new RSVP.Promise(function(resolve, reject) {
resource.save(function(err, resource) {
if (err) return reject(err);
resolve(resource);
});
});
}
Then in your calling code:
// ...
.then(function(resource) {
resource.name = req.body.name;
return save(resource);
})
.then(function(resource) {
// Whatever
})
.catch(function(err) {
// handle errors here
});
The other way of doing it would be to nodeify the save method, but I'd do it they way I've detailed above.

Resources