Are you looking for a way to deliver real-time data without spending weeks or months tinkering with code?
If that sounds like you, then Firebase might be the solution you've been searching for! Firebase is an amazing cloud-based platform that improves the usability and speed of development.
Disclaimer
This guide is not intended to be a definitive source of information on Firebase but rather a reflection of my own personal learning process.
The information has been collected from multiple sources, including outputs from A.I. and fact-checked to the best of my ability and should be viewed as my personal notes on the topic that have been shared publicly.
Please keep in mind that these notes might not be complete.
What is firebase
Firebase is a mobile app and web development platform created by Google.
Firebase provides an all-in-one solution for developers, including data storage and synchronization, user authentication, analytics and reporting.
The platform is designed to be secure and easy-to-use, connecting users quickly with their data and allowing them to interact with it securely from any device.
Firebase also supports authentication with email/password credentials and API authentication protocols from popular social media platforms like Google and Facebook.
Using Firebase, developers can quickly build powerful mobile and web applications with features like real-time updates, data synchronization across devices or servers, file storage services, and more.
The platform allows them to focus on building the app instead of worrying about backend operations or infrastructure.
Additionally, Firebase has tools to help you engage your users through notifications, customize messages based on user behaviour or location, A/B test features and monitor performance.
Data types
Firebase can store and synchronize various types of data, including JSON, but it also supports other data types such as binary data (e.g. images, audio, video) and strings. Additionally, Firebase provides services such as authentication, real-time database, cloud storage, and hosting, among others.
JSON
JSON (JavaScript Object Notation) is a lightweight, text-based format for storing and transporting data. It is often used to transmit data between a server and a web application, as well as between different parts of a web application.
JSON data is composed of key-value pairs, where the keys are strings and the values can be strings, numbers, booleans, objects, or arrays. Because of this structure, JSON is often used to store and transport data that is in the form of text. However, JSON is not limited to storing and transporting text data only, it can also store and transport other data types such as numbers and booleans.
Partition data
If a single document is under 1mb and pretty static is there any reason or benefit to still breaking this out into collections?
Whether or not to break out a single document into multiple collections depends on the specific use case and the structure of the data.
If the data is relatively static, meaning it doesn't change frequently or the changes are not frequent, and the size of the document is well under the 1MB limit, then there may not be any immediate benefit to breaking it out into multiple collections.
However, there are a few reasons why you might want to consider breaking out the data into multiple collections:
Scalability: As your data grows, it's easier to scale a collection-based data model than a document-based data model. If all your data is stored in a single document, it can become unwieldy to manage as the data size increases.
Ease of querying: If you need to query specific subsets of data frequently, it may be more efficient to store that data in its own collection, so you can query it directly rather than having to filter through the entire document.
Security: Firebase has a feature called "Firestore Security Rules" which allows you to set up fine-grained access controls for your data. If you have different types of data with different access requirements, it may be more secure to store them in separate collections so you can apply different security rules to each collection.
Data modeling: By breaking up your data into multiple collections, it can make it easier to model your data in a way that is consistent with the relationships between the different data types.
In general, it's good to think about your data and the expected usage, scalability and security requirements before making a decision about whether to break a single document into multiple collections.
Performance
Breaking out a single large document into multiple smaller collections is primarily done to improve the performance of search queries and reduce latency.
By breaking the data into smaller collections, you can more easily retrieve specific subsets of data and avoid querying the entire document.
It is important to consider the data model design and indexing to optimize the query performance.
Data model design: This refers to how the data is structured and organized within the collections. For example, if you are frequently querying for programs by network, it would be more efficient to store the network information in a separate collection and store a reference to that collection in the program document, rather than storing the network information in the program document itself.
Indexing: Firestore automatically indexes all fields in a document, but if you have specific fields that you will be querying frequently, you can create composite indexes for those fields. A composite index is an index that combines two or more fields of a collection or a document, which makes it easier to retrieve data based on multiple fields.
Composite indexes
Here's an example of how you might create a composite index in the Firebase Console:
In the Firebase Console, go to the "Indexes" tab in the "Firestore" section.
Click on the "Create index" button.
In the "Fields to index" section, select the "userId" and "status" fields.
Click the "Save" button.
This will create a composite index for the "userId" and "status" fields, which will make it more efficient to retrieve data based on those fields.
It's worth noting that when creating composite indexes, you should be mindful of the number of indexes and their size, as too many indexes can slow down writes and updates to your data.
By breaking the data into multiple collections, and optimizing the data model design and indexing you can effectively improve the performance of search queries and reduce the latency on your chrome extension.
Subcollection
In Firebase, you can partition data across multiple documents or collections by using the concept of "subcollections".
For example, let's say you have a collection called "users" that contains all the user data, and each user has multiple "orders". Instead of storing all the orders inside the user document, you can create a subcollection called "orders" inside the user document and store each order as a separate document inside that subcollection.
This way, you can retrieve all the orders for a specific user by querying the "orders" subcollection inside that user's document.
Here's an example of what the data structure might look like:
users: {
userId1: {
name: "John Doe",
email: "johndoe@example.com",
orders: {
orderId1: {
items: [{
product: "product1",
quantity: 2
}, {
product: "product2",
quantity: 1
}],
total: 100
},
orderId2: {
items: [{
product: "product3",
quantity: 1
}],
total: 50
}
}
},
userId2: {
name: "Jane Doe",
email: "janedoe@example.com",
orders: {
orderId3: {
items: [{
product: "product2",
quantity: 3
}],
total: 90
}
}
}
}
Denormalization
Another way to partition data is by using "denormalization" technique.
This is when you duplicate data across multiple documents or collections to make it easier to query and retrieve.
For example, let's say you have a collection of "users" and a collection of "orders".
Each order has a reference to a user.
Instead of querying the "users" collection every time you need to display order data, you could include the user's name and email in the order document.
This would make it possible to retrieve all the order data in a single query, without having to make a separate query to the "users" collection.
Here's an example of what the data structure might look like:
users: {
userId1: {
name: "John Doe",
email: "johndoe@example.com",
},
userId2: {
name: "Jane Doe",
email: "janedoe@example.com",
}
}
orders: {
orderId1: {
items: [{
product: "product1",
quantity: 2
}, {
product: "product2",
quantity: 1
}],
total: 100,
user: {
name: "John Doe",
email: "johndoe@example.com",
}
},
orderId2: {
items: [{
product: "product3",
quantity: 1
}],
total: 50,
user: {
name: "Jane Doe",
email: "janedoe@example.com",
}
}
}
It's worth noting that denormalization could lead to data inconsistencies if the data is not updated correctly.
Querying
Join
When using joins in Firebase, you can match the correct data by using a common key between the collections or documents that you want to join.
This key can be a unique identifier, such as an ID or a timestamp, that is present in both collections or documents.
For example, let's say you have two collections, "users" and "orders", and each order has a reference to a user. To join the data and retrieve all the order data along with the corresponding user data, you would use the user ID as the common key.
You can use the Firebase SDK to execute a query that retrieves the order documents and also include the corresponding user data. You can use the ".where" method and specify the user ID as the key and the value as the user ID you want to match.
Here's an example of how you might do this in JavaScript:
let ordersRef = firestore.collection("orders");
let usersRef = firestore.collection("users");
ordersRef.where("userId", "==", userId)
.get()
.then(querySnapshot => {
querySnapshot.forEach(orderDoc => {
let orderData = orderDoc.data();
let userRef = usersRef.doc(orderData.userId);
userRef.get().then(userDoc => {
let userData = userDoc.data();
console.log(userData);
console.log(orderData);
});
});
});
You can also use the ".join" method, which allows you to join multiple collections and retrieve the data in a single query. The method takes two parameters, the first one is the field you want to join on and the second one is the collection you want to join with.
Here's an example of how you might do this in JavaScript:
let ordersRef = firestore.collection("orders");
let usersRef = firestore.collection("users");
ordersRef.where("userId", "==", userId)
.join(usersRef, "userId", "==", "userId")
.get()
.then(querySnapshot => {
querySnapshot.forEach(orderDoc => {
let orderData = orderDoc.data();
console.log(orderData);
});
});
Keep in mind that when using joins, the number of documents and their size in the joined collections should be limited to avoid reaching the maximum document size of 1MB. Also, the query performance of joins can be affected when the collections or documents are too large.
JSON example
Here's an example of what the JSON data for each document in the "users" and "orders" collections might look like:
Users Collection
{
"userId1": {
"name": "John Doe",
"email": "johndoe@example.com",
},
"userId2": {
"name": "Jane Doe",
"email": "janedoe@example.com",
}
}
Orders Collection
{
"orderId1": {
"items": [
{
"product": "product1",
"quantity": 2
},
{
"product": "product2",
"quantity": 1
}
],
"total": 100,
"userId": "userId1"
},
"orderId2": {
"items": [
{
"product": "product3",
"quantity": 1
}
],
"total": 50,
"userId": "userId2"
}
}
As you can see, the "userId" in the "Orders" collection is used to match with the "userId" key in the "Users" collection to join the data.
It's also important to keep in mind the Firestore's best practices and limitations, such as indexing and data model design, in order to optimize the query performance.