Cloud Firestore + Android is just
Not so long ago, Google launched Cloud Firestore. Cloud Firestore is a cloud-based NoSQL database that Google positions as a replacement for the Realtime Database. In this article I want to tell how to start using it.
Opportunities
Cloud Firestore allows you to store data on a remote server, easily access it and monitor changes in real time. The documentation has an excellent comparison of Cloud Firestore and Realtime Database.
Creating and connecting to a project
In the Firebase console, select Database and click on Create database. Next, select the access settings. For familiarization, a test mode will be enough for us, but on prod it is better to approach this issue more seriously. Read more about access modes here .
To configure the project, perform the following steps:
- Add Firebase to the project according to the instructions from here.
- Add dependency to app / build.gradle
implementation 'com.google.firebase:firebase-firestore:18.1.0'
Now everything is ready.
To get acquainted with the basic techniques of working with Cloud Firestore, I wrote a simple application . To work, you need to create a project in the Firebase console and add the google-services.json file to the project in Android Studio.
Data storage structure
Firestore uses collections and documents to store data. A document is a record that contains any fields. Documents are combined into collections. A document may also contain nested collections, but this is not supported on android. If we draw an analogy with the SQL database, then the collection is a table, and the document is an entry in this table. One collection may contain documents with a different set of fields.
Receiving and recording data
In order to get all the documents of a collection, the following code is enough
remoteDB.collection(“Tasks”)
.get()
.addOnSuccessListener { querySnapshot ->
// Успешно получили данные. Список в querySnapshot.documents
}
.addOnFailureListener { exception ->
// Произошла ошибка при получении данных
}
}
Here we request all the documents from the Tasks collection .
The library allows you to generate queries with parameters. The following code shows how to get documents from the collection by condition
remoteDB.collection(“Tasks”)
.whereEqualTo("title", "Task1")
.get()
.addOnSuccessListener { querySnapshot ->
// Успешно получили данные. Список в querySnapshot.documents
}
.addOnFailureListener { exception ->
// Произошла ошибка при получении данных
}
}
Here we request all documents from the Tasks collection for which the title field corresponds to the value of Task1 .
Upon receipt of documents, they can be immediately converted to our data classes
remoteDB.collection(“Tasks”)
.get()
.addOnSuccessListener { querySnapshot ->
// Успешно получили данные. Список в querySnapshot.documents
val taskList: List = querySnapshot.toObjects(RemoteTask::class.java)
}
.addOnFailureListener { exception ->
// Произошла ошибка при получении данных
}
}
To write, you need to create a Hashmap with data (where the name of the field acts as the key, and the value of this field as the value) and transfer it to the library. The following code demonstrates this
val taskData = HashMap()
taskData["title"] = task.title
taskData["created"] = Timestamp(task.created.time / 1000, 0)
remoteDB.collection("Tasks")
.add(taskData)
.addOnSuccessListener {
// Успешная запись
}
.addOnFailureListener {
// Произошла ошибка при записи
}
In this example, a new document will be created and Firestore will generate an id for it. To set your own id do the following
val taskData = HashMap()
taskData["title"] = task.title
taskData["created"] = Timestamp(task.created.time / 1000, 0)
remoteDB.collection("Tasks")
.document("New task")
.set(taskData)
.addOnSuccessListener {
// Успешная запись
}
.addOnFailureListener {
// Произошла ошибка при записи
}
In this case, if there is no document with id equal to New task , then it will be created, and if there is, then the specified fields will be updated.
Another option for creating / updating a document
remoteDB.collection("Tasks")
.document("New task")
.set(mapToRemoteTask(task))
.addOnSuccessListener {
// Успешная запись
}
.addOnFailureListener {
// Произошла ошибка при записи
}
Subscribe to changes
Firestore allows you to subscribe to data changes. You can subscribe to changes to the collection as well as changes to a specific document
remoteDB.collection("Tasks")
.addSnapshotListener { querySnapshot, error ->
// querySnapshot - список изменений
// error - ошибка
}
querySnapshot.documents - contains an updated list of all documents
querySnapshot.documentChanges - contains a list of changes. Each object contains a modified document and type of change. 3 types of changes are possible
ADDED - the document is added,
MODIFIED - the document is changed,
REMOVED - the document is deleted
Loading large amounts of data
Realtime Database provides a less convenient mechanism for downloading large amounts of data, which consists in manually editing the json file and downloading it. Out of the box, Firestore provides nothing of the kind. It was very inconvenient to add new documents until I found a way to easily load a large amount of information. So that you do not have such problems as mine, below I will attach instructions on how to quickly and easily download a large amount of data. The instruction was found on the Internet.
- Install Node.js and npm
- Install the firebase-admin package by running the command
npm install firebase-admin --save
- Generate json file with collection data. An example can be found in the Tasks.json file .
- To download, we need an access key. How to get it is well described in this article.
- In the file export.js put down your data
require ('./ firestore_key.json') - a file with an access key. I was in a folder with a script- the name of your firestore database is
"./json/Tasks.json" - the path to the file in which the data is located
['created'] - a list of field names with the type Timestamp - Run the script
node export.js
The script uses the dalenguyen best practices
Conclusion
I used Cloud Firestore in one of my projects and did not experience any serious problems. One of my collections contains about 15,000 documents and queries on it are pretty fast and this is without the use of indexes. Using Cloud Firestore in conjunction with Room and Remote Config, you can significantly reduce the number of calls to the database and not go beyond free limits. At a free tariff per day, you can read 50,000 documents, record 20,000 and delete 20,000.