Writing and Reading Data in Cloud Firestore

Cloud Firestore is a NoSQL document database built for automatic scaling, high performance, and ease of application development. In this article, we will explore how to write and read data in Cloud Firestore along with complete with detailed examples and. Whether you are a beginner or looking to refine your understanding, this guide will walk you through the basics in a straightforward, easy-to-understand manner.

Getting Started with Cloud Firestore

Before we can start writing and reading data in Cloud Firestore, we need to set up a Firebase project and integrate Firestore into our app. Here’s a quick overview of the initial setup:

  • To create a Firebase project, go to the Firebase Console, click on “Add project” and then follow the setup instructions provided.
  • Register Your App: Register your app (iOS, Android or Web) with Firebase and download the configuration file (google-services.json for Android or GoogleService-Info.plist for iOS).
  • Integrate Firebase SDK: Add the Firebase SDK to your project.

For detailed setup instructions, refer to the Firebase documentation.

Writing Data to Cloud Firestore

Writing data to Firestore involves creating documents and collections. Each document is a set of key-value pairs, and collections are containers for documents.

1. Basic Write Operations

Setting Up Firestore in Your App

First, let’s ensure that your app is properly set up to use Firestore. Below are snippets for different platforms:

import { initializeApp } from "firebase/app";
import { getFirestore, collection, doc, setDoc } from "firebase/firestore";

// Your Firebase config object
const firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_PROJECT_ID.firebaseapp.com",
projectId: "YOUR_PROJECT_ID",
storageBucket: "YOUR_PROJECT_ID.appspot.com",
messagingSenderId: "YOUR_SENDER_ID",
appId: "YOUR_APP_ID"
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);

Explanation: This code initializes a Firebase app using the provided configuration object and sets up Firestore as the database for the app. It imports the necessary Firebase modules, configures the app with specific project details, and establishes a connection to Firestore for performing database operations.

Adding a Document to a Collection

To add a document to a collection, you can use the setDoc method. This method allows you to create a new document or overwrite an existing document.

Example: Adding a User

Let’s add a user to a users collection. Each user will have a name, email, and createdAt field.

import { doc, setDoc } from "firebase/firestore";

// Create a reference to the users collection
const userRef = doc(db, "users", "userId123");

// Set the user's data
await setDoc(userRef, {
name: "John Doe",
email: "john.doe@example.com",
createdAt: new Date().toISOString()
});

Explanation:This code snippet demonstrates how to add a document to a Firestore collection. It creates a reference to a document in the “users” collection with the ID “userId123” and then uses the `setDoc` method to set the user’s data, including name, email and the creation timestamp. If the document already exists, it will be overwritten with the new data.

Adding a Document with Auto-Generated ID

Firestore can automatically generate a unique ID for your document if you don’t want to specify one.

import { collection, addDoc } from "firebase/firestore";

// Create a reference to the users collection
const usersRef = collection(db, "users");

// Add a new document with an auto-generated ID
const newUserRef = await addDoc(usersRef, {
name: "Jane Smith",
email: "jane.smith@example.com",
createdAt: new Date().toISOString()
});

console.log("New user added with ID: ", newUserRef.id);

Explanation:This code snippet demonstrates how to add a new document to a Firestore collection with an automatically generated ID. It creates a reference to the “users” collection and uses the `addDoc` method to add a document with the specified user data (name, email, and creation timestamp). Upon successful addition, the document ID is logged to the console.

Reading Data from Cloud Firestore

Reading data from Firestore involves querying collections and documents. You can fetch individual documents, entire collections, or perform queries with filters.

1. Basic Read Operations

Fetching a Single Document

To fetch a single document, use the getDoc method.

import { doc, getDoc } from "firebase/firestore";

// Create a reference to the user document
const userRef = doc(db, "users", "userId123");

// Fetch the document
const userSnap = await getDoc(userRef);

if (userSnap.exists()) {
console.log("User data:", userSnap.data());
} else {
console.log("No such document!");
}

Explanation:This code snippet shows how to fetch a specific document from Firestore. It creates a reference to a user document in the “users” collection and uses the `getDoc` method to retrieve it. If the document exists, it logs the user data; otherwise, it logs a message indicating that the document does not exist.

2. Fetching All Documents in a Collection

To fetch all documents in a collection, use the getDocs method.

import { collection, getDocs } from "firebase/firestore";

// Create a reference to the users collection
const usersRef = collection(db, "users");

// Fetch all documents
const querySnapshot = await getDocs(usersRef);

querySnapshot.forEach((doc) => {
console.log(`${doc.id} =>`, doc.data());
});

Explanation:This code snippet demonstrates how to fetch all documents from a Firestore collection. It creates a reference to the “users” collection and uses the `getDocs` method to retrieve all documents. It then iterates through the query snapshot, logging the ID and data of each document.

3. Querying Data

Firestore allows us to perform complex queries to fetch data based on specific criteria.

Example: Fetching Documents with a Condition

Suppose we want to fetch all users who signed up after a certain date.

import { collection, query, where, getDocs } from "firebase/firestore";

// Create a reference to the users collection
const usersRef = collection(db, "users");

// Create a query against the collection
const q = query(usersRef, where("createdAt", ">", "2023-01-01T00:00:00Z"));

// Fetch matching documents
const querySnapshot = await getDocs(q);

querySnapshot.forEach((doc) => {
console.log(`${doc.id} =>`, doc.data());
});

Explanation:This code snippet demonstrates how to query a Firestore collection with a condition. It creates a reference to the “users” collection and constructs a query to fetch documents where the “createdAt” field is greater than January 1, 2023. It then retrieves and logs the matching documents.

4. Updating Data

To update an existing document, use the updateDoc method. This method only updates the specified fields, leaving other fields unchanged.

Example: Updating a User’s Email

import { doc, updateDoc } from "firebase/firestore";

// Create a reference to the user document
const userRef = doc(db, "users", "userId123");

// Update the user's email
await updateDoc(userRef, {
email: "new.email@example.com"
});

Explanation:This code snippet updates the email field of a user document with the ID “userId123” in the “users” collection. It uses the `updateDoc` method from Firestore to perform the update operation.

5. Deleting Data

To delete a document, use the deleteDoc method.

Example: Deleting a User

import { doc, deleteDoc } from "firebase/firestore";

// Create a reference to the user document
const userRef = doc(db, "users", "userId123");

// Delete the document
await deleteDoc(userRef);

Explanation:This code snippet deletes a user document with the ID “userId123” from the “users” collection. It uses the `deleteDoc` method from Firestore to perform the delete operation.

Batch Writes and Transactions

Batch writes allow you to execute multiple write operations as a single atomic unit. This means that either all of the operations succeed, or none of them do.

Example: Batch Write

import { writeBatch, doc } from "firebase/firestore";

// Initialize a batch
const batch = writeBatch(db);

// Create references to the documents
const userRef1 = doc(db, "users", "userId1");
const userRef2 = doc(db, "users", "userId2");

// Set data for each document
batch.set(userRef1, { name: "Alice", email: "alice@example.com" });
batch.set(userRef2, { name: "Bob", email: "bob@example.com" });

// Commit the batch
await batch.commit();

Explanation:This code snippet demonstrates how to use batch writes in Firestore to execute multiple write operations as a single atomic unit. It initializes a batch, creates references to two user documents (“userId1” and “userId2”), sets data for each document, and commits the batch to apply the changes atomically.

1. Transactions

Transactions are used when you need to read a document and then write to it based on the read data. Firestore ensures that the transaction is executed atomically.

Example: Transaction

import { runTransaction, doc } from "firebase/firestore";

// Create a reference to the user document
const userRef = doc(db, "users", "userId123");

// Run the transaction
await runTransaction(db, async (transaction) => {
const userSnap = await transaction.get(userRef);

if (!userSnap.exists()) {
throw "User does not exist!";
}

const newEmail = "new.email@example.com";
transaction.update(userRef, { email: newEmail });
});

Explanation:This code snippet demonstrates how to use transactions in Firestore. It creates a reference to a user document (“userId123”), then runs a transaction to update the user’s email. The transaction first checks if the user document exists, and if so, updates the email field to “new.email@example.com”.

2. Real-Time Updates

Firestore can listen to changes in your data in real-time, allowing your app to stay up-to-date without polling the server.

Example: Real-Time Listener

import { doc, onSnapshot } from "firebase/firestore";

// Create a reference to the user document
const userRef = doc(db, "users", "userId123");

// Listen for real-time updates
onSnapshot(userRef, (doc) => {
if (doc.exists()) {
console.log("Current data: ", doc.data());
} else {
console.log("No such document!");
}
});

Explanation:This code sets up a real-time listener for changes to a specific user document (“userId123”). When the document is modified, the listener logs the current data of the document. If the document doesn’t exist, it logs “No such document!”.

Conclusion

Overall, Cloud Firestore offers a flexible and scalable solution for managing your apps data. By following the instructions in this guide, you can set up Firestore in your app, perform basic write and read operations, query data, and using advanced features like batch writes, transactions and real-time updates. Understanding these fundamental concepts will enable you to harness the full potential of Cloud Firestore in your applications.