WWCode Talks Tech #12: Let’s Get Fired Up: Getting started with Firebase Firesto
Written by Navati Jain
We create apps at Loblaw Digital to support our various banners and the pharmacy, the loyalty online ordering, and our own clothing brand. Firebase is a platform that can support your app development journey in multiple ways. If you are a front-end dev and your code is for the web or for mobile apps, and you're focusing more on the front end, then you can use Firebase for a lot of the back-end tools. It can also support server-side applications. There are many other services to help with maintaining your app. Firebase was an independent company and was acquired by Google in 2014. When you open Firebase, the console, it is a nice, friendly, and colorful webpage. There is a menu of the multiple services that Firebase offers. You can use the authentication SDKs to authenticate your app with providers like Google, Facebook, and Twitter. You may have encountered those sign-in options where they ask you, do you want to sign in with Gmail or Facebook?
App Check is new. This provides attestation so that you know that the request is coming from your authentic app and from an authentic device. There is the Firestore Database. There's also a Realtime Database. It was the initial database that they had. There are some differences, as well as some similarities between the two. Extension is a new thing that Firebase offers. We have hosting functions, and machine learning, and there are tons of these services. We have release and monitoring. You may have used Crashlytics performance so that you can see how your app is doing or where it's crashing. There's also Test Lab and App Distribution, and the list does not end here. There are also analytics and engagement.
There are two types of database services. There's the relational database, and there's NoSQL. A relational database is schema-based and is typically implemented as tables. With NoSQL, we have non tabular formats. There's the Realtime DB as well as Firestore. Both of them are NoSQL DBs. You may be familiar with relational databases. In a relational database, it's a table, like a spreadsheet that you have with Excel or Google Sheets.
The important thing here is it is schema oriented, which means that it's really important when it comes to the columns, what the columns are going to look like, and which column will serve as the primary key. What are the relationships between the tables? In a table with the list of some of my favorite TV shows, there are various columns. We can use the first column, the series ID as the primary key. We can uniquely identify each of these rows. We can have some constraints. We can say that the title should always be a string. There should be a certain length for this title. It should not be allowed to be null. Similarly, I can say that the number of seasons should always be an integer. We have a schema established. We can have another table where we can track the different episodes watched. We can use the episode ID as the primary key. We can create a relationship between the two tables, I can use the series ID from the first table, and I can use that as a foreign key.
You may know that the query language for relational databases is SQL or a structured query language. There are so many constraints around the schema, as well as relationships. This can get resource-intensive when you try to scale. If you're trying to scale, you would need to invest in your host machine to improve the processing power.
On the other hand, with no SQL, we don't have this rigorous scheme-based approach with all these constraints. Scaling is easier, and you can scale with a horizontal scale approach, which means that you can distribute the database across several machines. The focus is on speeding up queries, and you have the flexibility to add fields more easily. There are various ways to implement a NoSQL DB. You have the key value-based approach where there's a key and a value. There's also the wide column-based approach where not all those need to have the same columns. There is the graph-based DB, where there are entities that are nodes with static relationships, just like in social networks. The document-based DB is like a JSON.
The advantage of SQL is there is a flexible structure. However, relational databases are very useful. It is very powerful, especially when it comes to queries. Queries here are more customizable. If you're not sure of the kind of queries you need and you need more options, you can run a lot of different types of customizable queries with SQL. You can add filters, use WHERE clauses, and match different string patterns. NoSQL, on the other hand, is useful when you know the access pattern, which means that you know what kind of queries you plan to run. The benefit is better performance and lower latency.
Firestore is a JSON-like document. There are keys and values. You can have the name, age, and value, and you can also have something a bit more nested, like an address. Also with Firestore, it is a collection of documents. So keep this visual in mind. Think of a folder with various files. Firestore is a collection of documents. I could have documents point to more than one collection too. Firestore is pretty flexible. When it comes to these documents in Firestore, you are retreating the entire document. You are unable just to retrieve parts of the documents. Keep that in mind when you're planning your database. Also, there is a limit. The size of the document should be less than one MB. Firestore has a part of security rules to control access. So you can create rules around who can access which documents and which collections. You have access rules, and you can also use security rules for creating validation rules. You can make sure that there are parameters around the values entered.
We know that Firestore is a collection of documents. To build this collection of documents, we start with the collection, and inside that, we can place various documents. I can have a document for a meetup that I attended on Android. Maybe I attended a workshop on blockchain and one, of course, for Firebase, as well as I, read a book on SQL. I have my base collection established. Looking at one of these documents, I can add some data. I can keep track of the name of the activity. What was the type of activity? Was it a meetup? Was it a conference? Was it an online course? And I can also have other relevant information, like, in this case, today's event is organized by Women Who Code, maybe I have an instructor for a course, the author of a book, all of that information, and I can store most of this using strings. I could also have the rating so that I know how much I enjoyed the event.
I can run a query and say, how many of my events are equal to meetup? I'm using a WHERE clause. I'm saying activity type is equal to meetup. This will help me find all my events that have this condition met. Another simple query that I can run is how many of my events did I enjoy? If my enjoyment threshold begins at seven, I can say where field rating is greater than seven. So that would give me all the events that match this condition. When it comes to executing any of these queries, there are two ways to go about it. One is you can just run the query one time and leave it at that.
We have indexes and there is a composite and single index. An index is a data structure that is a sorted list of all the values of your database. It has the values as well as the location of the element. Think of an academic book and how they have the index at the very end of the book. Similarly, that's how Firestore also maintains an index. We have Firestore creating an index for us. It keeps all these different fields in a certain manner. It also keeps track of where they can be found in the database. Firestore creates an index for almost all your fields automatically. And if you want, you can tell Firestore to create exceptions to that. Thanks to this auto-indexing, we are able to retrieve data very quickly. It might take a little long in terms of storing, but the retrieving part is so much quicker.
Firestore is able to intersect two indexes very easily with its own algorithm. But if you're trying to run a query where I'm saying I want an activity equal to meet up and rating greater than seven. I'm using an equality operator as well as a range operator, the greater than the operator. Here, for Firestore to intersect is not possible. If you think you're going to need such queries in your app, then you can create an additional index that can catenate these two fields. And that kind of index is called a composite index. It's pretty simple to create a composite index. All you need to do is hit this query once from your app, and it's going to say you're not allowed to create because you need to create a composite index. It will also give you a link. Click on that link, and it generates the query for you.
If you find yourself posting on social media like me, you might want also to consider storing the write-up information in this database. We can store it as another long string. I can store it as an array of strings so that if I have multiple write-ups, I can have one for Twitter, one for LinkedIn, which might be longer, and so on. That is definitely one way to go about it. I can also store write-ups in a nested form. I can have other associated fields like the date that I posted it on, the medium that I used, or which social media platform I used. When I use this nested structure, it is called a map in Firestore. I can store this as an array of maps. Let's say you're building an app that displays all these different activities. I'm storing the basic information. I'm displaying the name of the event and the type, and the organizer. As a user, I only see some of the fields. I'm not getting an entire description. I cannot see the write-ups unless I click on one of these rows. Then I get detailed information.
I could store my write-ups as a sub-collection. I can place them in their own collection of write-ups. Each of my write-ups could be in its own documents. I could even have some activities which may not have their own sub-collection because you don't necessarily have a write-up for everything. If you run a query on how many of these events I post about on Twitter, here I'm trying to span across various sub-collections. I'm trying to combine the various sub-collections, even though Firestore is actually creating an index only for the sub-collection separately. If you find yourself in this situation, then you can use a collection group query so that Firestore can combine the index for all these different sub-collections.
Let's talk about when you go to those events, and you make new contacts. One approach could be to store them as a sub-collection. You could also consider another approach. You could use a top-level collection, which means that I could place the new connections that I made in a collection at the same level as my write-up, and my activities. I can have another collection of these people at the same level as my activities. Now they're at the top level. If you're trying to figure out which of these two approaches to go for, then you need to figure out what kind of queries you are likely to run.