Firebase Database Functions

How to write a trigger that adds a created date to a node

For the latest re-write of my cricket quiz app I’m using Firebase realtime database. One of the data items I want to store in it are the users’ Firebase notifications push tokens, along with their username, user id, etc. I also thought it would be useful to have a created date automatically generated for each user node, mainly for information purposes, but also I thought it might come in useful at some point. (Or maybe it’s just because I’m a dinosaur that comes from a traditional RDBMS environment.)

This is how the user data looks in the firebase console before I’ve created the function

Screen Shot 2017-06-27 at 06.42.02

I didn’t want the created date to be generated by the client app, so I thought this gives me an ideal opportunity to try out the new cloud functions just released for Firebase. Functions can be fired by many actions in Firebase, one of which is a data write event on the realtime database.

To develop functions you first need to install Node.js on your development machine, which is easily done by downloading and installing this package. This also installs the npm package manager which you will use when setting up firebase functions. Once this is done, open a terminal window and install the firebase command line interface:

You then need to login to firebase, type this into the terminal window:

This will display a url in the terminal window which you can either click on to open a browser window, or copy and paste into a browser window. From the browser page you can then login to firebase.

Next create a new folder for your firebase functions project and initialise the project by typing the following command,  respond yes when it asks about installing dependencies using npm.

You’re all ready now to create your first database cloud function. The initialisation will have created a folder called functions, and in that folder will be a node js file called index.js. Edit this file to add cloud functions.

The first things you need to add to the index.js file are the import statements to setup the required functions, and the initialisation of firebase admin:

I need to create a function that will be triggered for every write operation on a certain database node. The root node that I want the trigger to fire on is  '/v0/users' But if I use that path for the function, the trigger will fire  on every data node below that path whenever there is a write operation, which is not what I want. So I will specify a wildcard parameter in the node path by surrounding the wildcard with braces, that way the function will only run against the data node that matches the wildcard, i.e. the specific userId that the write is being performed on: '/v0/users/{userId}' .

I’ll name the function createDate, export it so it can be used globally, and pass it the database node path as the ref:

This has created a function that will be triggered for every database write that matches the specified path, but the function body is empty so it doesn’t do anything. Now on to writing the function body.

My first attempt at the function was very simple:

This gets the current date in ISO format and writes it to the database node that has just been written to. There’s an obvious problem with this – writing the created date triggers the function again, which writes the created date and triggers the function again… This recursive function eventually exceeded my firebase resource limits and failed.

What I needed to do was check whether the data being written is new or an already existing user. If it’s an existing user check if the ‘created’ field is present in the data being written, if it is I know the write was triggered by my function, if it’s not I know it’s an update from a client so I can grab the existing created date and add it to the new data that is being written:

Note here that I’m using event.data.previous  which is the existing data (if any) in the node about to be written to, and event.data.child  which is the data about to be written to the node.

This works nicely. The only other issue is that I couldn’t now delete any users, a delete was triggering the function which would re-create the user with just the ‘created’ field. This is easy to overcome by just checking the data about to be written, if it’s empty then it’s a delete operation and so return without doing anything:

The full index.js file now looks like this:

To deploy this to firebase just type this command at the command line:

And this is how the database looks after creating a new user with a username and push token, and the function creating the created date:

Screen Shot 2017-06-27 at 07.34.18

Leave a Reply

Your email address will not be published. Required fields are marked *