What is Firestore and why use Firestore?
- NoSQL
- Hosted, serverless with autoscaling.
- You are billed by number of operations (read, write, delete), database storage and network bandwidth.
- Realtime updates: auto synchronization across devices and with backend.
- Offline support on client.
- Mobile/Web Client Library: Android, iOS, Web
- Server Client Library: C#, Go, Java, Node.js, PHP, Python, or Ruby
Imagine a database server which client (web, Android, iOS) can access directly, with security rules and read/write/delete operation can trigger cloud functions (imagine stored procedure for RDBMS).
You can have a backend database server without a typical backend (thus no backend coding is required).
For authentication, you can use Firebase Authentication.
NOTE: Firestore introduction video
Firestore vs Datastore
Google Cloud Datastore is a server-side NoSQL database (cannot be accessed from Web/Frontend JavaScript, iOS or Android), thus no realtime updates/auto synchronization/offline feature.
The lastest version of Datastore is also known as Cloud Firestore Datastore Mode. Important new feature is strong consistency.
Firestore is capable of partial update, which Datastore doesn't support.
Cloud Firestore Native Mode
is commonly known as Firestore
.
The previous database on Firebase is known as Firebase Realtime Database
NOTE: Cloud Firestore Native Mode vs Datastore Mode, Google Cloud Datastore vs Firestore
NOTE: Cloud Firestore or Realtime Database
Enable Firestore
Goto Firebase Console and create a new project (or import an existing Google Cloud project).
Select Database
(from the left panel menu) and click Create Database
.
NOTE: Enabling Cloud Firestore will preclude you from using Cloud Datastore with this project, notably from the associated App Engine app. Each project can only use Firestore (Cloud Firestore Native Mod) or Datastore (Cloud Firestore Datastore Mode), not both.
NOTE: Firestore become GA (out of Beta) since 31 Jan 2019.
When selecting Cloud Firestore Security Rules, I would recommend Locked mode
(Test mode
just seems too dangerous with your database access wide opened).
NOTE: Cloud Firestore Security Rules only apply to Mobile/Web Client Library: Android, iOS, Web. The server client libraries bypass all Cloud Firestore Security Rules and instead authenticate through Google Application Default Credentials. If you are using the server client libraries or the REST or RPC APIs, make sure to set up Cloud Identity and Access Management for Cloud Firestore.
Setup Android Environment
Add Firestore dependencies to Module:app build.gradle
.
dependencies {
// https://firebase.google.com/support/release-notes/android#latest_sdk_versions
implementation 'com.google.firebase:firebase-firestore:18.0.1'
}
Initialize Firestore.
val db = FirebaseFirestore.getInstance()
I bump into java.lang.IllegalStateException: Default FirebaseApp is not initialized in this process com.luasoftware.nuanxindan. Make sure to call FirebaseApp.initializeApp(Context) first.
error when trying to run the app. I need to use google-services:4.2.0.
Edit Project build.gradle
.
buildscript {
dependencies {
classpath 'com.google.gms:google-services:4.2.0'
}
}
Add Data
Write some code to add data to collection test
.
val db = FirebaseFirestore.getInstance()val item = mapOf( "name" to "Desmond", "born" to 1979, "active" to true)db.collection("test") .add(item) .addOnSuccessListener { doc -> Timber.d("Add success: ${doc.id}") } .addOnFailureListener { e -> Timber.w("Add fail", e) }
NOTE: Collection (test
) is like a Table, while Document (item
) is like a Record/Row
When you run the code, you will probably run into com.google.firebase.firestore.FirebaseFirestoreException: PERMISSION_DENIED: Missing or insufficient permissions.
. This is expected as we previously select Locked mode
when we create the database.
NOTE: addOnSuccessListener
and addOnFailureListener
would not be called if the backend could not be reached (when no network access).
Security Rules
Edit the Firestore Security Rules: Firebase Console -> Database -> Rules
.
Edit the rules to allow read/write access to test
collection.
service cloud.firestore { match /databases/{database}/documents { match /{document=**} { allow read, write: if false; } match /test/{testId} { allow read: if true; allow write: if true; } }}
You can test the rule by using the Simulator
(on the bottom left corner of the rule).
Click Publish
and the new rule will take 1 minute to take effect.
Try to run the add data code again.
Read Data
db.collection("test") .get() .addOnSuccessListener { result -> for (document in result) { Timber.d("${document.id}: ${document["name"]}") } } .addOnFailureListener { e -> Timber.w("Add fail", e) }
References: