MongoDB: Execute Javascript Functions using Command line

Your browser does not support in page playback.

Usually, it is too easy to integrate MongoDB with any language and make queries. But what if we don't want to set this up in a particular language and execute the commands from the command line itself.

When I moved to MongoDB, I was using it with Node and Mongoose and I was like I could do this with my eyes shut. But, the real problem I faced when I wanted to extract some data (using aggregations) without setting up a Node project (I was too lazy to set that up). I knew the commands so I didn't have to face any problems in creating queries, but writing all the queries in a single command itself was very tiresome, and if we make any mistake, we have to use arrow keys to move into our code (I know you can relate to this). Also, if the queries are too long and you want to change them frequently, it is not a good idea to write everything in a single command. We need to make things modular by splitting the code/logic into separate files. And we're going to do the same in this article.

In this article, we'll see how we can execute JavaScript using various methods from our terminal. I'll show how we can use eval, a single javascript file, and importing a collection of javascript files to make things modular.


Connecting to the database

Okay, so first thing first. Let's first connect to the database to make queries. If you just want to connect to your database locally, you don't have to worry about anything. You can simply use this command:

mongo dbName

Here, we can also run mongo without passing database name and select that database using use dbName in the Mongo Shell.

In the command below, we've included the host localhost followed by the port 27017 and then our database. I guess now you can easily figure out how to connect to the remote MongoDB instance.

mongo localhost:27017/dbName

You can also pass --host flag but I like to do it this way. However, the default Mongo setup doesn't allow/accept external connections. (That's why I'm writing this, otherwise I'm too lazy to add this too).

To allow external devices to connect to our instance,

  1. We can make changes in the mongod.conf file or
  2. We can start a daemon process with bind_ip argument

Modifying the "mongod.conf" file

In Mac OS, if you've installed this using Homebrew, the default path of the config file is: /usr/local/etc/mongod.conf

In this file, you can see the value of bind_ip is 127.0.0.1. So if you want to allow all the incoming connections, change it to 0.0.0.0 (or your specific IP to restrict the access).

For Ubuntu, it is: /etc/mongod.conf

You can see the bindIp set to 127.0.0.1. Make the same changes as I mentioned above.

Start MongoD by passing arguments

If you're willing to start a Mongo instance using mongod, you can pass bind_ip [1] argument to allow other connections.

mongod --bind_ip=0.0.0.0

Note: We can also bind multiple IP addresses in both cases. You can check the references[2] to get more idea. But for now, we're ready to move forward.


Now we know how to connect to the local and remote Mongo instances. So let's start with the simple example. In this example, we'll create a database and a collection. Then we'll insert some sample data into it and try to fetch all the data from command-line by passing javascript functions and files.

Create a Database

In MongoDB, there is no command to create a database and sometimes it is frustrating because if you have a typo, you'll still be able to use that new database. So, let's create our new database blog after connecting to the Mongo instance using mongo command without any database name. To create our new database, execute this command:

use blog

Create a Collection

After switching to our database blog, we need to create a collection. Fortunately, we have a command to create this. We'll create a collection named users. We can also pass some other options in the second argument[3].

db.createCollection('users')

Run this command to check if the collection is created successfully:

show collections

Insert Data

Let's insert some data to run our queries later. We'll add 2 rows containing 2 fields name and email.

db.users.insertMany([
  { name: 'Alice', email: 'alice@example.com' },
  { name: 'Bob', email: 'bob@example.com' }
])

Run this command to check whether the data is inserted properly:

db.users.find()

Execute Queries using --eval Flag

At this stage, we're ready to execute CRUD operations on our data. First, let's see how we can do this using --eval. To do this, we'll run the simple query to fetch all the data that we inserted in the steps above. For that, we'll run the following command:

mongo blog --eval "db.users.find().toArray()"

After the execution, we can see some information about the different things of the MongoDB, and our data is below that. In our command, there is .toArray() method. Which converts all the data into an array so that we can make use of this data later.


Execute Queries from a JavaScript file

Now just imagine that you want to make some gigantic queries (let's say stage 3+ aggregations) and you want to change them frequently to do different tasks and you're just using arrow keys to move and don't even know if the brackets are properly closed (Okay enough mental torture!).

For that, you definitely need a file so that you can clearly see the query and format it using your favorite linters. And it's a wonderful feature of MongoDB that you can actually insert a file to execute the command. Let's see how we can do this. Create any javascript file, I'll name it findByEmail.js. and insert this data into it.

To execute this file, run the following command:

mongo blog < findByEmail.js

We can use our basic linux command's knowledge to store the output in a file.

// To override previous data
mongo blog < findByEmail.js > output.json

// To append to the existing data
mongo blog < findByEmail.js >> output.json

Execute Queries after importing Multiple files

You may think that now I'll say what if we have hundreds of files and want to make code modular - which is true. If this is the case, generally I prefer to do this by setting up a proper project in my machine and connect the instance with a well-known connector of that language. But you're not here on this blog to take my wisdom on how to set up a project, and MongoDB also has something more to offer.

To achieve this modularity, MongoDB supports a function: load()[4]. We can pass the path of a file as an argument of this function. Let's see this in action.

Now, let's create 2 different javascript files: first will feed the data and second will fetch the new data. First, we want to execute the insert operation, so we'll load this file in the second file which has some logic to fetch the data. So, feed.js would look like this:

db.users.insert(
  { email: 'john@example.com', name: 'John' }
);

And retrieve.js can look like this:

// assuming that feed.js is in the same directory
load('./feed.js');

db.users.find().toArray();

Now simply we can execute this retrieve.js file same as above. We'll also store this data in some file to run some other operations later.

And just in case if you want to delete this database blog, make sure you're inside this database (otherwise you may end up deleting some other database) and run this command.

db.dropDatabase();

Footnotes

I hope you've learned something from this article, and if you think something is wrong or have some suggestions, do let me know. Also, if you've enjoyed this, please subscribe to our newsletter to get the updates. We won't spam you!


References

  1. https://docs.mongodb.com/manual/reference/program/mongod/
  2. https://docs.mongodb.com/manual/core/security-mongodb-configuration/
  3. https://docs.mongodb.com/manual/reference/method/db.createCollection/
  4. https://docs.mongodb.com/manual/reference/method/load/