node-red-contrib-cloud-firestore 3.1.0

Node-RED nodes to handle google cloud firestore read and write operations.

npm install node-red-contrib-cloud-firestore

Node-RED nodes to handle google cloud firestore read and write operations.

For any assistance, contributions or stars, visit the repo.

Install

Install from the palette manager

node-red-contrib-cloud-firestore

Install from npm

npm install node-red-contrib-cloud-firestore

Usage

Admin configuration

A configuration property under either Read or Write nodes that initializes a firebase app taking in a name and the json contents of your apps service account credentials which can be generated under Project settings > service accounts > Firebase Admin SDK.

Firestore Read

Node fetches data from a referenced collection, subcollection or document.

Configurations can be made within the node or on the msg.firestore property:

  • collection: [string] The collection or subCollection in reference
  • document: [string] The document reference under the defined collection
  • realtime: [boolean] telling the node to listen for live updates or not (false by default)
  • group: [boolean] fetch all documents under collections with the above supplied collection name (false by default)
  • query: [array<object>] an array of objects defining query methods to apply to the read
  • disableHandler: [boolean] disables the default snapshot handler, returning a built query reference as the payload (false by default)

Response data from the operation is output through the msg.payload property

Upstream input queries

To perform dynamic queries with the read node through input, you need to supply an array of objects on the msg.firestore.query property in the order they will be chained with the query method as the only property and it's value being an array of arguments, or a single string value as show below.

{
  query : [
      {where: ["state", "==", "CA"]},
      {where: ["population", "<", 1000000]}
  ]
}

// reference.where("state", "==", "CA").where("population", "<", 1000000)
{
  query : [
      {orderBy: "name"},
      {limit: 2}
  ]
}

// reference.orderBy("name").limit(2)
{
  query : [
      {where: ["population", ">", 100000]},
      {orderBy: ["population", "asc"]},
      {limit: 2}
  ]
}

// reference.where("population", ">", 100000).orderBy("population", "asc").limit(2)
{
  query : [
      {orderBy: "population"},
      {startAt: 100000},
      {endAt: 1000000}
  ]
}

// reference.orderBy("population").startAt(100000).endAt(1000000)

Custom snapshot handler

You can also write your own snapshot handler under the expert zone accordion. The editor is similar to the core function node & but supports the following global objects: config (the nodes settings), snap (query snapshot), util(nodejs), msg, context, RED.util & console. The Promise, Buffer and Date objects are also supported.

The snap object contains the resulting query snapshot.

Do remember that what you return will then be sent as the output payload. The following example returns an array of objects, while logging to the cmd console

const docs = [];
let added = context.flow.get('added');

snap.docChanges().forEach(change => {
    docs.push(change.doc.data());
    if (change.type === 'added') {
      added++;
      console.log('Added: ', change.doc.data());
    }
    if (change.type === 'modified') {
      console.log('Modified: ', change.doc.data());
    }
    if (change.type === 'removed') {
      console.log('Removed: ', change.doc.data());
}
});

context.flow.set('added', added);  
return docs;

Additionally, you can also save your snippets into the snippet library by giving it a file name and clicking the Save to Library button

Realtime edge cases

If you intend on passing in dynamic configurations from an upstream node while still having realtime enabled, the node will not have your upstream values recorded during the next restart. This could result in some unexpected outcomes.

A way around this would be for the node to store your most recent settings from the interface / upstream nodes into node-red's provided storage mechanism.

To enable this workaround in the node, you'll have to change your instances default storage module from memory to localfilesystem in your settings.js file. Read more on this here

Firestore Write

Node performs write operations to the referenced collection, subCollection or document.

Configurations made from within the node or on the msg.firestore property:

  • operation: [string] Write operation to perform, either add, set, update or delete
  • collection: [string] collection or subCollection reference to write to.
  • document: [string] document reference to write to (optional for add operations)
  • options: [object] additional options passed to firebase (currently specific to set operations)

Handling Firestore classes & sentinels

Due to the nature of Cloud firestore's implementation, some actions need special handling.

Arrays

To perform array updates, you'll need to wrap your elements in an object with the _arrayUnion or _arrayRemove property to add or remove elements respectively within an array

msg.payload = {
  animals: {
      _arrayUnion: 'goats'
  },
  farmers: {
      _arrayRemove: {name: "John Doe"}
  }
}

becomes:

msg.payload = {
  animals: firestore.FieldValue.arrayUnion("goats"),
  farmers: firestore.FieldValue.arrayRemove({name: "John Doe"})
}

GeoPoints

Objects within the payload received by the Write Node containing a _lat and _lng property will be replaced with the appropriate GeoPoint class

msg.payload = {
     farm:{
         location: {
              _lat: -1.232134,
              _lng: 36.123131
         },
         fence: [
              {_lat: -1.433434, _lng: 35.123324},
              {_lat: -1.673214, _lng: 36.126541},
              {_lat: -1.334124, _lng: 34.342131}
         ]
    }
}

becomes:

msg.payload = {
  farm: {
      location: new firestore.GeoPoint(-1.232134, 36.123131),
      fence: [
          new firestore.GeoPoint(-1.433434, 35.123324),
          new firestore.GeoPoint(-1.673214, 36.126541),
          new firestore.GeoPoint(-1.334124, 34.342131)
      ]
  }
}

Server Timestamp

Properties with the _serverTimestamp string value will be replace with the appropriate serverTimestamp sentinel

msg.payload = {
  time: '_serverTimestamp'
}

becomes:

msg.payload = {
  time: firestore.FieldValue.serverTimestamp()
}

Increment

Properties with the _increment string value will be replaced with the appropriate increment sentinel

msg.payload = {
  itemCount: {
    '_increment': 30
  }
}

becomes:

msg.payload = {
  itemCount: firestore.FieldValue.increment(30)
}

Delete

Properties with the _delete string value will be replaced with the appropriate delete sentinel

msg.payload = {
  unwantedField: '_delete'
}

becomes:

msg.payload = {
  unwantedField: firestore.FieldValue.delete()
}

Extensibility & additional use cases

Mustache templating

Both the read & write nodes support mustache templating on the collection & document properties, which allows you to cherry pick your collection / document properties directly from the msg object.

For example, setting the collection field to {{col}} with a message object like

msg = {
  col: "users"
}

will have the corresponding node run operations against the users collection.

Firebase instances

Both the read & write nodes can expose a firebase object that contains the current app instance and a reference to the firebase admin sdk, which allows you to extend the node to your liking. Simply enable the eject property in the ui / via an upstream input.

// upstream input / via the ui
msg.firestore = {
 eject: true
};

// output
msg.firebase = {
 "app": "...", // current firebase instance
 "admin": "...", // firebase admin sdk
};

TODO

  • Handle transactions and batch writes

Node Info

Version: 3.1.0
Updated 1 year, 10 months ago
License: MIT
Rating: 5.0 3

Actions

Rate:

Downloads

220 in the last week

Nodes

  • firebase admin
  • Firestore in
  • Firestore out

Keywords

  • cloud firestore
  • firestore
  • firebase
  • node
  • node-red
  • google

Maintainers

Contributors

  • Jean-Baptiste Richardet