Power Prototyping with MongoDB and Node-RED

Do you want to be able to quickly get your database backend fronted by a web service? Node-RED and MongoDB can be a powerful ally in your strategy and we'll show you how.

Whether you're just getting started with a small toy project or about to embark on "The Next Big Thing"®, being able to quickly set up a backend to your application can be the key to getting your project off the ground. With the widespread use of JSON as the de-facto serialization format for data structures on the web, JSON document databases such as MongoDB are excellent platforms for prototyping new applications.

However, exposing MongoDB directly to the client-side of your application is difficult to manage, hard to keep efficient, and pushes logic into your client applications. In this article, we'll use Node-RED and MongoDB to build a minimal RESTful API for a photographer's portfolio website.

Getting Started

Accessing a MongoDB Instance

You should first spin up a spin up a Compose MongoDB database with SSL enabled or start your own local instance of MongoDB. Starting a new deployment on Compose is the easiest way to get started.

Installing Node-RED

You should also have access to a running installation of Node-RED. If you already have NodeJS on your local machine, you can use the Node Package Manager from a terminal to install Node-Red: npm install node-red.

If you don't have NodeJS yet, you can download the installer for your platform directly from the NodeJS website.

Install the mongodb2 node

Node-RED is a flow-based programming (FBP) environment, so connecting to services requires access to a "node" that provides the services you need. In this article, we'll connect to MongoDB using the node-red-node-mongodb2 package. You can install it by selecting the Manage Palette option from the main menu, searching for the mongodb2 node and clicking install.

Connecting to MongoDB using Node-RED

To connect to MongoDB, you must first configure the mongodb2 node. Start by dragging the mongodb2 node onto the Node-RED canvas.

The node initially has a red error indicator letting you know that the node needs to be configured. Double-click on the node to open the configuration editor.

In the top section labelled "server", ensure that "Add new mongodb2..." is showing in the drop-down menu and click on the "pencil" icon to add a new server configuration.

The configuration section has all of the information Node-RED needs to connect to MongoDB. You can find the connection string in your Compose console by clicking on your database name and clicking the Admin tab:

Once you've configured a MongoDB node, it will be available for every
subsequent MongoDB node you create by selecting it from the drop-down menu.

Retreiving and Querying Records (HTTP GET)

We're now ready to start adding the HTTP endpoints to our RESTful portfolio API. All of our endpoints will use the same route location but different HTTP methods to GET, POST, PUT, and DELETE items in the portfolio. We'll start with the GET endpoint. To add an HTTP endpoint, we'll use the HTTP input node which comes installed by default in all new instances of Node-RED. In the future we can also add other interfaces such as WebSockets and RabbitMQ, but for now we'll stick with HTTP.

To add a new HTTP endpoint, drag the HTTP input node onto the canvas.

Double-click the node to open the configuration panel and add the URL and method you prefer (in this case, we'll start with the GET HTTP method). Since we're working with a data entity called "project", we'll make each of our endpoints available at the /projects URL.

We'll also store each of these projects in a database collection called "projects". Double-click on the mongodb2 node and type projects in the collection field. Then select the find.toArray operation from the operation drop-down and click done.

Next we'll wire together our mongodb2 node and HTTP input. This can be done by clicking on the out port on the right of the HTTP input node and dragging a wire to the in port on the left of the mongodb2 node as shown below. We'll also need to drag an HTTP output node onto the canvas to ensure that our HTTP client receives a response. Finally, click deploy to publish the flow and make the endpoints active.

If you're running Node-RED locally, You can now access your endpoints at http://localhost/projects. Any query string parameters you pass to the URL will be available in the msg.payload object. Since the find method in the mongodb2 node also reads in the msg.payload object, we can use this wiring to automatically send all parameters passed into the HTTP input node to the mongodb2 node. The mongodb2 node also expects the msg.payload to be an array, and if you pass in an array to a call like updateOne which accepts several parameters, each value in the array will be passed as a parameter to that call. This is the same behavior as the Mongo Native driver, and more details can be found in the mongo driver documentation

For example, to search for a project with a title field matching “test” in the MongoDB shell, the following MongoDB query would look like:

db.projects.find({ "title": "test" });

The query also could be executed using the following CURL command:

curl -X GET localhost/projects?title=test

Creating the Remaining RESTful Endpoints

The other endpoints follow a similar structure: they start with an HTTP input node, send parameters into the mongodb2 node configured with the desired operation, and send the results as a response back to the user. In this next section, we'll cover the Create, Update, and Delete operations.

Create a New Project (HTTP POST)

To create a new project in MongoDB, we'll send an HTTP POST request to the /projects endpoint. This is similar to what we did above with the GET request, except we have to extract project data from the POST request's body rather than the query string parameters.

The HTTP input node does not send form body data in the msg.payload object, however we can access form body data directly using the msg.req object. The msg.req object contains the underlying HTTP request from ExpressJS, so POST form data can be found in the msg.req.body object. We can copy the msg.req.body over to the msg.payload by adding a function node in our flows.

We'll start by copying the GET flow and pasting the copy onto the canvas. Then we'll modify the HTTP input node to use the POST method instead of the GET method.

Now we’ll drag a function node onto the canvas and place it between mongodb2 and the HTTP input node.

Then, we'll add the following code to the function node:

msg.payload = msg.req.body;  
return msg;  

Finally, configure mongodb2 to use the projects collection and the insert operation and click Deploy.

You can use the following CURL command to create a new project with a title field and a value of "test":

$ curl -X POST -H "Content-Type: application/json" -d '{"title":"test"}' localhost/projects
{ "_id": ObjectID("2fae32498ac2b113ca241543bfcaef"), "title": "test"}

Update an Existing Document (HTTP PUT)

Continuing on with RESTful convention, we'll use the HTTP PUT method to update an existing project. Let's copy the nodes we created for the POST method and modify the HTTP node to use PUT and change the mongodb2 operation to update. Since the document to update will be passed in through the request body, we'll keep the copied function node as it is.

The PUT command includes the ID in an object in the body of the request, along with the fields that you want to update. The following CURL command will update an existing project:

$ curl -X PUT -H "Content-Type: application/json" -d '{"_id": "2fae32498ac2b113ca241543bfcaef", "title":"not test"}' localhost/projects
{ "_id": ObjectID("2fae32498ac2b113ca241543bfcaef"), "title": "not test"}

Deleting an Existing Document (HTTP DELETE)

The last of the CRUD operations we need to implement is DELETE. We'll use the HTTP DELETE method to do this. HTTP DELETE is similar to HTTP GET in that it does not send a form body along with the request. To send the ID of the record to be deleted we'll encode it in the URL like this: /projects/id_to_delete.

Copy the flow we created for PUT in the previous section and paste the copy onto the canvas. Then, modify the Method field in the HTTP input node by clicking on the node and selecting the DELETE method from the drop-down menu. In the URL field we can insert /project/:id which adds the URL parameter id.

We'll exploit the msg.req object again, this time to get the URL parameters from the msg.req.params object. To do this, we’ll add a function node to move the msg.req.params object over to the msg.payload by double-clicking on the function node and adding the following code to the editor:

msg.payload = msg.req.params;  
return msg;  

Finally, we’ll update the mongodb2 node's operation field to deleteOne.

You can delete an item with an ID of "2fae32498ac2b113ca241543bfcaef" by using the following CURL command:

$ curl -X DELETE localhost/projects/2fae32498ac2b113ca241543bfcaef
{ "_id": ObjectID("2fae32498ac2b113ca241543bfcaef")}

Wrap-Up

MongoDB, with its schema-less architecture, and Node-RED, with its flow-based programming model, make a powerful rapid-prototyping duo. Node-RED also makes it possible to expand out the functionality of our minimal API as much as we want, thanks to its flexible programming model and robust community of third-party nodes. In the next installment, we'll move your API out of the prototype phase by adding authentication to your exposed endpoints using JSON Web Token.


If you have any feedback about this or any other Compose article, drop the Compose Articles team a line at articles@compose.com. We're happy to hear from you.