Skip to Main Content

TWIL 2019-10-25

Image from the "TWIL" blog post showing how Firebase tools integrate with JavaScript and React-Native for app development.

Welcome to "TWIL," our series designed to be your weekly dose of micro-learning. In this session, Marisa takes us through the interconnected world of Firebase: Firestore, Storage, and Cloud Functions. Learn how to build real-time apps with React-Native by using Firebase’s suite of tools to update Firestore documents with video paths from Cloud Storage asynchronously, all orchestrated via Cloud Functions. Lean in as we unveil the streamlined process of linking documents to media, a valuable snippet for developers looking to enhance functionality in real-time applications.

Firebase: Firestore, Storage and Cloud Functions 🤝

Use case

Say we have a document stored in Firestore. We upload a video to Cloud Storage, and we want to take the path of the video and add it to the document in Firestore. We can use Cloud Functions to accomplish this!

Video Data Document

{
	scheduled: "September 18, 2019 at 10:30:00 AM UTC-4",
	completed: "September 18, 2019 at 10:28:00 AM UTC-4",
	file: "<cloud-storage-url>", // updated after video has finished uploading
}

Firestore

let documentID = ""

try {
  // Get or Create a collection reference
  const collectionRef = firestore().collection(
    `company/${COMPANY_ID}/client/${CLIENT_ID}/videos`,
  )

  // Grab the docuemnt reference so that we can get the document id at the end of the path
  const documentRef = await collectionRef.add(clientData) // `add` will auto-id this document for us
  documentID = documentRef.path.split("/")[5]

  console.log("*** Firestore reference created and uploaded at:", documentRef.path)
} catch (error) {
  console.log("*** Firestore - error getting collection:", { error })
}

Cloud Storage

// Record a video and return the data for it
const data = await camera.recordAsync(options)

// Get the storage object reference at the specified path (we use the same path as the document in firestore)
const reference = storage().ref(
  `company/${COMPANY_ID}/client/${CLIENT_ID}/videos/${documentID}.mov`,
)
console.log("*** Storage reference created at:", reference.fullPath)

// Put the video file at the reference path
reference.putFile(data.uri)

Cloud Function

const functions = require("firebase-functions")
const admin = require("firebase-admin")

admin.initializeApp()
const firestore = admin.firestore()

/**
 * Triggered by a new object being created in Storage.
 *
 * - Check if the object is a video, if not, return.
 * - If so, get the corresponding Firestore document reference for this video. The paths should match.
 * - Update the document reference with the file path for the uploaded video.
 */
exports.updateDocument = functions.storage.object().onFinalize(async object => {
  const { contentType } = object
  const filePath = object.name

  // Exit if this is triggered on a file that is not a video
  if (!contentType.startsWith("video/")) {
    return console.log("This is not a video.")
  }

  // Get document reference for this filePath
  const documentRef = await firestore.doc(filePath.replace(".mov", ""))

  // Update document with filepath for uploaded video
  await documentRef.update({ file: filePath })
  return true
})
  • JavaScript
  • React-Native
  • Firebase
  • Google Cloud Storage
  • Google Cloud Functions
  • Async
Marisa Gomez's profile picture
Marisa Gomez

Senior Software Engineer

Related Posts