CRUD with Cloud Firestore and Node.js by Google Cloud Function

2022/10/065 min read
bookmark this
Responsive image

Pre Requirement

This blog will focus on how to use the Google Cloud Function to handler CURD operation with Cloud Firestore. Below is the simple diagram of the process, but before we start you'll need prepare below list to make sure it is ready

Cloud Functions to Firestore

  • have GCP account
  • setup GCP project
  • setup GCP fireStore collection
  • create a service account and add Cloud Datastore Owner and download to the local repo folder

Setup npm repo

Now, let's get started, first we'll need to initialize the npm repo by run the following command on your local. This will create package.json file with default setting.

npm init -y

Next, install the @google-cloud/functions-framework so can test the cloud function locally later.

npm install --save-dev @google-cloud/functions-framework

To test locally, will need to add following task to the package.json as well.

  "start": "npx functions-framework --target=main [--signature-type=http]"

Also, will install the following npm package firebase-admin so will be able to communicate with firebase and fireStore.

npm install --save firebase-admin

Adding code to interact with fireStore

Once we have the npm package installed, we can start adding code. First, let's create a file index.js, and will add the following code to start handle CRUD with fireStore.

Here, we'll initialize the fireStore and add service account json, so we can communicate with fireStore from local environment.

const { initializeApp, cert } = require('firebase-admin/app');
const { getFirestore } = require('firebase-admin/firestore');

const serviceAccount = require('./service-account-has-fireStore-role.json');
initializeApp({
  credential: cert(serviceAccount),
});

Start prepare the CRUD operation

We'll create following operation at this blog, a basic CRUD operation from cloud function to the fireStore database.

  • Read Data - [HTTP GET] - http://localhost:8080/?docid=800
  • Create Data - [HTTP POST] - http://localhost:8080/
{
	"docid": "2000",
	"id": "test_10",
	"list": [1,2,3]
}
  • Update Data - [HTTP PUT] - http://localhost:8080/?docid=800
{
	"id": "test_10",
	"list": [1,2,3]
}
  • DELETE Data - [HTTP DELETE] - http://localhost:8080/?docid=800

Read Data - [HTTP GET]

First step, we'll handle the http get for the read operation, here we check http method is GET, and has the querystring docid.

exports.main = (req, res) => {

if (req.method === 'GET') {
    if (!req.query.docid) {
        return res.status(404).send('');
    }

    db.collection('my_collection').doc(req.query.docid.toString()).get()
    .then(doc => {
        return res.status(200).send(doc.data());
    });
}

Below is how it's looks like once we run the npm run start to test on my local with postman. Cloud Functions to Firestore

Create Data - [HTTP POST]

For create data, we'll expect the http is POST and body has below JSON object structure.

{
	"docid": "200",
	"id": "test_10",
	"list": [10,20,30,40]
}

Once get the request.body, we'll set as showing below, basically using the fireStore's set function, which can be using as create or update for the target collection's document.

exports.main = (req, res) => {

    else if (req.method === 'POST') {

        db.collection('my_collection')
        .doc(req.body.docid)
        .set({
            id: req.body.id,
            list: req.body.list
        })
        .then((doc) => {
            return res.status(200).send(doc);
        });
    }

Below is how it's looks like once we run the npm run start to test on my local with postman. HTTP Post with fireStore

Update Data - [HTTP PUT]

Here we'll continue using the set function for the update operation.

exports.main = (req, res) => {

    else if (req.method === 'PUT') {
        db.collection('my_collection')
        .doc(req.query.docid)
        .set({
            id: req.body.id,
            list: req.body.list
        })
        .then((result) => {
            return res.status(200).send(result);
        });
    }

Below is how it's looks like once we run the npm run start to test on my local with postman. HTTP Put with fireStore

Delete Data - [HTTP DELETE]

For the delete we'll just expect the querystring passing the docid and use delete for remove from the fireStore database.

exports.main = (req, res) => {

    else if (req.method === 'DELETE') {
        db.collection('my_collection')
        .doc(req.query.docid).delete()
        .then((result) => {
            return res.status(200).send(result);
        });
    }

Below is how it's looks like once we run the npm run start to test on my local with postman. HTTP Delete with fireStore

The whole index.js file for CRUD operation

This below snippet contains the all the CRUD code we just mentioned earlier.

const { initializeApp, applicationDefault, cert } = require('firebase-admin/app');
const { getFirestore, Timestamp, FieldValue } = require('firebase-admin/firestore');

const serviceAccount = require('./none-firebase-admin-firm-champion-365105-f0d88d6192e2.json');

initializeApp({
    credential: cert(serviceAccount)
});

const db = getFirestore();

exports.main = (req, res) => {

    if (req.method === 'GET') {
        if (!req.query.docid) {
            return res.status(404).send('');
        }

        db.collection('my_collection').doc(req.query.docid.toString()).get()
        .then(doc => {
            return res.status(200).send(doc.data());
        });
    }
    else if (req.method === 'POST') {

        db.collection('my_collection')
        .doc(req.body.docid)
        .set({
            id: req.body.id,
            list: req.body.list
        })
        .then((doc) => {
            return res.status(200).send(doc);
        });
    }
    else if (req.method === 'PUT') {
        db.collection('my_collection')
        .doc(req.query.docid)
        .set({
            id: req.body.id,
            list: req.body.list
        })
        .then((result) => {
            return res.status(200).send(result);
        });
    }
    else if (req.method === 'DELETE') {
        db.collection('my_collection')
        .doc(req.query.docid).delete()
        .then((result) => {
            return res.status(200).send(result);
        });
    }
}

Deploy Node.js code to the Cloud

For deployment, you can use the gcloud to deploy from your local or tight with CI/CD, or deploy from cloud bucket as zip file, but here we'll just deploy from your local folder to the cloud.

below is the sample command that deploy to the google cloud function as name with my-firestore-function and other options, once it is done, should be seen a URL from the console or you can find your cloud function, if you browser the URL with the querystring docid, now should be seen JSON response from the fireStore database.

gcloud functions deploy my-firestore-function --trigger-http --region=us-central1 --runtime=nodejs16 --gen2 --allow-unauthenticated --entry-point=main

Conclusion

Above are few steps that demonstrate how to use cloud function as HTTP(S) request server and communicate with fireStore NoSQL database as back-end server. Both Google cloud function and fireStore are serverless and host in the cloud, so you can focus your business logic and no need to worry about the underneath server.