As stated by Google:
“Cloud Firestore is a flexible, scalable database for mobile, web, and server development from Firebase and Google Cloud Platform. It keeps your data in sync across client apps through realtime listeners and offers offline support for mobile and web so you can build responsive apps that work regardless of network latency or Internet connectivity. Cloud Firestore also offers seamless integration with other Firebase and Google Cloud Platform products, including Cloud Functions”
Besides the aforementioned and it being easy to setup, it has a free usage policy for low traffic use (as of July 1, 2020, it’s free up to 50000 reads/day, 20000 writes/day and 20000 deletes/day) that allows its free use for many applications and, if needed, growth is not a problem.
The following web resources are of interest to users of Firestore with AppGyver:
Firestore documentation: https://cloud.google.com/firestore/docs
Firestore concepts: https://cloud.google.com/firestore/docs/concepts
Since this tutorial is about using Firestore as a data resource for AppGyver REST API direct integration, not Firestore itself, it will assume a basic knowledge of the Firestore setup.
Firestore uses the following methods, not all of which are implemented in AppGyver at the present time:
AppGyver REST API direct integration implemented
Gets multiple documents
Starts a new transaction
Commits a transaction, while optionally updating documents
Creates a new document
Deletes a document
Gets a single document
Lists all the collection IDs underneath a document
Updates or inserts a document
Rolls back a transaction
Runs a query
While all Firestore methods are usable through an HTTP direct call, only those using the REST API direct integration will be presented. Additionally a workaround for querying collections based on field contents in the client side will also be shown.
The following actions can be executed using the available methods in the AppGyver REST API direct integration:
Use with Firestore
GET COLLECTION (GET)
Get all documents in a collection (ordered by field if necessary)
GET RECORD (GET)
Get one document in a collection if the ID is known
CREATE RECORD (POST)
Create a new document (with a custom ID if necessary)
DELETE RECORD (DELETE)
Delete one document in a collection if the ID is known
CREATE RECORD (POST)(4)
The following are the data types allowed by Firestore as they should be referenced in the schemas (taken from Firestore REST API)
orderby is not the same as
Since Firestore has a rather unique structure it is very important to pay attention to have an exact match on the schemas of the document and those in the AppGyver REST API:
Every document in Firestore has always the following keys:
updateTime. Never omit them in your schemas, except as noted in the CREATE RECORD (POST) method.
fields key is an object with properties that have your actual data in objects with the name of your fields with a pair
key will denote the data type.
If your fields are composite, you will have also
Example of a simple document schema in AppGyver REST API:
Although you can have schemas to match any data structure you create on your Firestore database, it will be a lot easier if you keep the structure as simple as possible. This means to try to avoid composite fields as much as possible.
If in doubt, use the Firestore API explorer: https://cloud.google.com/firestore/docs/reference/rest/v1/projects.databases.documents
The document id is part of the name of each document. It is the string after the last slash as shown:
To get the
id assigned by Firestore:
where pageVars.id is the name of the document, and the value "20" is the length of the string that Firestore assigns to document id's.
Since free use of Firestore caps at 50000 reads/day, it is advisable to delete the recursive read in the data variable set up, or the quota will be reached in a few hours:
As shown in the Firestore REST API Methods section:
AppGyver doesn't have a PATCH method so the only way to change the content of a field is to GET the full document, DELETE the original document, change the data of the specific field and CREATE a new document. Care should be taken if the documentId can not be changed, in which case the new document should be created with the old id (Creating document with custom id).
Since the POST method is set in AppGyver to create a new record but, as shown in the Query document by field section, can be set for other uses with some tinkering, maybe all Firestore uses for the method can be set. Be aware of the limitation for the structured query response as noted in the server side query.
All AppGyver methods use a common base for each resource. In order to have flexibility and following the rules of Firestore, the following applies:
The remainder of the URL will be set up for each method and will have the following mask:
The following image shows the config setup:
Once you setup the Relative path and the Response key path, run a test to check if you get the data, and if so, set schema from response.
The response will be an array with all documents in your database, ordered by default (document id). If you want the response ordered by the contents of a specific field, add:
to the Relative path as shown in the following image for the collection "Permisos" to be ordered by the values of the field "nombPermiso".
By default, the order will be lexical, ascending, but can be set to descending order by adding "desc" to the Relative path after the field name, separated by a space:
Both methods use the same configuration strings. The following image shows the config setup in tab GET RECORD (GET):
Use the same strings and URL placeholder setup in the DELETE RECORD (DELETE) tab.
The following image shows the config setup:
The setup shown in the above image will create a document with a documentId set by Firestore, 20 characters long.
The Create record (POST) request schema has to be manually created by adding properties starting with fields as the example shows:
This has to match the data schema in Firestore. Note that the schema starts with the fields object and does not include the name, createTime and updateTime fields.
If you want to set your own id, you should add the following to the Relative path after the collection name:
and set a URL placeholder as show in the following image:
Also, you have to pay attention to the URL placeholder properties as needed for your application.
Firestore uses the HTTP method POST with a very powerful structured query payload in the body of the call. However, since the POST method implemented in AppGyver is, up to now, designed to create a new document (record), if you want to process the query server side, the CREATE RECORD (POST) AppGyver method can be used, but will need some twisting.
So there are two possible alternatives to query the database: Server side and Client side.
For the use of the structured query, you have to set a new resource with the base set up with a :runQuery required by Firestore. The CREATE RECORD (POST) base configuration should be set up as shown:
Note that there is no collection id but instead ":runQuery", which needs a structured query in the body payload of the POST call. For help setting the query, it is strongly suggested that you use the Firestore API explorer (https://cloud.google.com/firestore/docs/reference/rest/v1/projects.databases.documents).
In order to set the structured query in the body payload of the method call, a Create record (POST) request schema has to be set. In the simplest form, it will be as follows:
which is equivalent to a body:
Every empty values ("") have to be set with a variable or a static string in the method call as will be shown ahead.
Also a Create record (POST) response schema that matches the Firebase response has to be set. For the example above, it will be:
In the image, the object "nombInmueble" is the name of the field that is to be retrieved with the query.
The property "fields" has to have as objects the keys of the fields you will get in the response dependent on the way the structured query was set up in the request schema (either one field or all of them).
The properties "document", "createTime", "fields", "name" and "readTime" are mandatory.
Also, you have to set a data variable to get the response of the query. For the example, it will be:
And a page variable to use the data, as show for the example:
As can be seen above, the variable named "datos" its a list that has an schema that exactly matches the Create record (POST) response schema that was set above.
Then, the flow logic will be as shown, with a Create Record function followed by a Set page variable to assign the response to the variable (in this example "datos") using a formula.
The flow logic will look like this:
The Create Record function bindings will look like this:
Values have to be set with variables or static values as required. Note that the arrays (Custom list) have to be set too. See the following example which sets the collection id (first Custom list on the image above):
The operators ("op") can be any of:
field value < specified value
field value <= specified value
field value > specified value
field value >= specified value
field value == specified value
field array contains specified value
field == at least one of the specified values in a given array.
The given array values can't be empty values.
The given array can't have more than 10 values.
field array contains any of the specified values in a given array
The given array values can't be empty values
The given array can't have more than 10 values
The variable ("datos" in the example) is assigned the values of the POST response with a formula as shown:
Although the validation of the formula shows an error, the value returned by POST is actually an array and will be bound to the variable and usable.
The data will then be available as usual.
The data variable of input1 (listaProyectoTramite in the image) is the one set by the GET COLLECTION method.
The page variable (PTF in the image) and the Output schemas should be configured as the Firestore document schema (note that the variable type is array of objects). For the example above:
Then, the data will be available using the Page variable.
That's it! You've learned to integrate a Firestore database with your AppGyver Composer app, and should be ready to start utilizing Firestore in your own project. If you enjoyed the tutorial, be sure to give Eduardo a shout out on the forums!