Skip to content

Firestore

Kyle Szklenski edited this page Jun 13, 2023 · 28 revisions

Contents on this page:


Class Table

Class Description
Firestore Firestore module, lets user connect to collections, issue queries and request a list of documents/collections at a specified path.
FirestoreCollection A reference to a colleciton in Firestore, used to call functions to manage documents or nested collections.
FirestoreDocument An object representing a fetched, updated or deleted document in Firestore.
FirestoreTask Result of any request issued through Firestore. Processes the request, emits signals and returns a result.
FirestoreQuery An object representing a query to Firestore, used as a parameter for the query() function.


Firestore

Firebase.Firestore

Functions Description
collection(collection_path: String) -> FirestoreCollection Create a reference to a collection inside Firestore. Returns a reference to a collection.
list(collection_path: String) -> FirestoreTask List all contents of a collection in Firestore.
Returns a FirestoreTask issuing the request.
query(firestore_query: FirestoreQuery) -> FirestoreTask Issue a query on Firestore.
Returns a FirestoreTask issuing the request.

Properties Description
collections: Dictionary A Dictionary containing all referenced collections.
auth: Dictionary A Dictionary containing all auth info for the current authenticated user.

Signals Description
listed_documents(documents: Array) Emitted when the list() request is processed successfully by a FirestoreTask.
result_query(result: Array) Emitted when the query() request is processed successfully by a FirestoreTask.
error(error: Dictionary) Emitted when a query() or list() request is not processed successfully by a FirestoreTask.

***

FirestoreCollection

Firebase.Firestore.collection()

Functions                                          Description
add(document_id: String, fields: Dictionary) -> FirestoreTask Add a Document to a Collection.
If document_id is an empty string, the id will be randomly generated by Firebase.
update(document_id: String, fields: Dictionary) -> FirestoreTask Update a specified document in a collection. If document_id is an empty string, the id will be randomly generated by Firebase, creating a new document.
Similarly, if the document with the given document_id does not exist, it will be created.
get(document_id: String) -> FirestoreTask Get a specific document.
delete(document_id: String) -> FirestoreTask Delete a specific document.

Properties Description
config: Dictionary Configuration settings for this plugin.
auth: Dictionary Authentication dictionary to issue requests as a logged user.
collection_name: String The referenced collection's name

Signals Description
add_document(document_added: FirestoreDocument) Emitted when the add() request is processed by a FirestoreTask.
update_document(document_updated: FirestoreDocument) Emitted when the update() request is processed by a FirestoreTask.
get_document(document_got: FirestoreDocument) Emitted when the get() request is processed by a FirestoreTask.
delete_document() Emitted when the delete() request is processed by a FirestoreTask.
error(code, status, message) Emitted when a request has not processed correctly by a FirestoreTask.


FirestoreDocument

FirestoreDocument.new() or from a signal

Functions Description
static dict2fields(dictionary: Dictionary) -> Dictionary Parse a GDScript Dictionary to a Firebase dictionary of fields.
static fields2dict(fields: Dictionary) -> Dictionary Parse a Firebase dictionary of fields to a GDScript Dictionary.
_to_string() -> String Automatically called on print(document) to print a formatted document.

Properties Description
doc_name: String The document name.
doc_fields: Dictionary The document fields, as a GDScript Dictionary.
create_at: String Timestamp of creation date.

Signals Description

***

FirestoreTask

returned by a Firestore request

Functions Description

Properties Description
data: Variant Contains the result of a processed Task.
action: int Contains the action the task is processing or has processed.

Signals Description
task_finished(result: Variant) Emitted when a Task has been processed. Returns the result of the request as a parameter. This is a lower level of signal communication between FirestoreTasks, Firestore and your application. In general, you should not use this, but instead one of the following signals.
listed_documents(documents: Array) Emitted when the list() request is processed successfully.
result_query(result: Array) Emitted when the query() request is processed successfully.
error(error: Dictionary) Emitted when a query() or list() request is not processed successfully.
add_document(document_added: FirestoreDocument) Emitted when the add() request is processed.
update_document(document_updated: FirestoreDocument) Emitted when the update() request is processed.
get_document(document_got: FirestoreDocument) Emitted when the get() request is processed.
delete_document() Emitted when the delete() request is processed.
error(code, status, message, task) Emitted when a request has not processed correctly.


FirestoreQuery

FirestoreQuery.new()

Properties Description
doc_name: String The document name
doc_fields: Dictionary The document fields, as a GDScript Dictionary
create_at: String Timestamp of creation date

Functions Description
select(fields: Variant) A SELECT query in a collection; fields can be an Array/PoolStringArray of fields, or just a String for a single field.
from(collection_id: String, all_descendants: bool = true) A FROM query in a single collection
from_many(collections: Array) A FROM query across multiple collections. collections must be an Array of Arrays of type [collection_id:String, all_descendants:bool].
where(field: String, operator: FirestoreQuery.OPERATOR, value: Variant, chain: int = -1) A WHERE query to match fields' values with Operators.
operator must be a FirestoreQuery.Operator element.
chain can be OPERATOR.AND or OPERATOR.OR to chain multiple where() in sequence. The last one in a chain (or if a single one) must have chain = -1 (automatically injected).
order_by(field: String, direction: int = DIRECTION.ASCENDING) An ORDER BY query in a collection. Direction must be of type FirestoreQuery.DIRECTION. You must have an index defined in the Firebase console in order to use this query type.
order_by_fields(order_field_list : Array) An ORDER BY query in a collection based on multiple fields. order_field_list must be an Array of Arrays with structure [field: String, order: DIRECTION]. You must have an index defined in the Firebase console in order to use this query type.
start_at(value: Variant, before: bool) A START AT query in a collection. value can be of any type. If true, before lists values before the specified one; if false, then after.
end_at(value: Variant, before: bool) An END AT query in a collection. value can be of any type. If true, before lists values before the specified one; if false, then after.
offset(offset: int) An OFFSET query in a collection. Defines the amount of results to be skipped in a query.
limit(limit: int) A LIMIT query in a collection. Defines the max number of results to be returned.

Back


Connect To A Collection

Note you need to be authenticated for this to work

Firebase.Firestore.collection('COLLECTION_NAME')

The following will return a collection from Firestore called firestore_collection. This collection can be called on later when adding or getting documents from it.

var firestore_collection : FirestoreCollection = Firebase.Firestore.collection('COLLECTION_NAME')

Back


Back


Get A Document

Note you need to be authenticated and connected to a collection for this to work

# 3.x
firestore_collection.get(documentId: String) -> FirestoreTask
# 4.x
firestore_collection.get_doc(documentId: String) -> FirestoreTask

Note: Unlike collections (which is just a reference) this function won't directly return a document. It will request the specified document, which will be returned with a signal.
The following methods will let you return a document from Firestore with the DOCUMENT_ID that is specified to an object called firestore_document of type FirestoreDocument:

  1. Call the #4.x .get_doc() or #3.x .get() function and then yield for the collection to return it with a signal
# 3.x
var collection: FirestoreCollection = Firebase.Firestore.collection(COLLECTION_ID)
collection.get(DOCUMENT_ID)
var document: FirestoreDocument = yield(collection, "get_document")

- or -

var collection: FirestoreCollection = Firebase.Firestore.collection(COLLECTION_ID)
var document_task: FirestoreTask = collection.get(DOCUMENT_ID)
var document: FirestoreDocument = yield(document_task, "get_document")
  1. Connect a signal to the collection and get the document separately
var collection: FirestoreCollection = Firebase.Firestore.collection(COLLECTION_ID)
collection.connect("get_document",self,"_on_get_document")
collection.get(DOCUMENT_ID)

[...]

func _on_get_document(document: FirestoreDocument) -> void:
    pass

# 4.x
var collection: FirestoreCollection = Firebase.Firestore.collection(COLLECTION_ID)
var document = await collection.get_doc(DOCUMENT_ID)

- or -

var collection: FirestoreCollection = Firebase.Firestore.collection(COLLECTION_ID)
var document_task: FirestoreTask = collection.get_doc(DOCUMENT_ID)
var document: FirestoreDocument = await document_task.get_document
  1. Connect a signal to the collection and get the document separately
var collection: FirestoreCollection = Firebase.Firestore.collection(COLLECTION_ID)
collection.get_document.connect(_on_get_document)
collection.get_doc(DOCUMENT_ID)

[...]

func _on_get_document(document: FirestoreDocument) -> void:
    pass

The following will parse the data into a human readable format with automatic parsing, from Firebase format to Dictionary.

print(firestore_document)

Back


Add A Document

Note you need to be authenticated and connected to a collection for this to work

.add(documentId: String, fields : Dictionary = {}) -> FirestoreTask

The following will add a new document into Firestore by first creating the object, and then adding it.

# 3.x
var add_task: FirestoreTask = firestore_collection.add("DOCUMENT_ID", {'name': 'Document Name', 'active': 'true'})
var document: FirestoreTask = yield(add_task, "task_finished")

- or -

var document = yield(add_task, "add_document")

- or -

var document = yield(Firebase.Firestore, "add_document")

# 4.x

var add_task: FirestoreTask = firestore_collection.add("DOCUMENT_ID", {'name': 'Document Name', 'active': 'true'})
var document = await add_task.task_finished

- or -

var document = await add_task.add_document

- or -

var document = await Firebase.Firestore.add_document

Internally, the FirestoreCollection instance will call the dict2fields() function to convert the dictionary of fields into the correct format for Firestore to use.

Note: if "DOCUMENT_ID" is left as an empty String, Firebase will assign a random name to this document. This name will be returned through the appropriate FirestoreCollection signal.

Back


Update A Document

Note you need to be authenticated and connected to a collection for this to work

.update(documentId: String, fields: Dictionary = {}) -> FirestoreTask

The following will update document in Firestore.

# 3.x
var up_task: FirestoreTask = firestore_collection.update("DOCUMENT_ID", {'name': 'Document Name', 'active': true})
var document: FirestoreDocument = yield(up_task, "task_finished")

- or -

var document: FirestoreDocument = yield(up_task, "update_document")

- or -

var document: FirestoreDocument = yield(Firebase.Firestore, "update_document")

# 4.x
var up_task: FirestoreTask = firestore_collection.update("DOCUMENT_ID", {'name': 'Document Name', 'active': true})
var document = await up_task.task_finished

- or -

var document =  await up_task.update_document

- or -

var document = await Firebase.Firestore.update_document

Internally, the FirestoreCollection instance will call the dict2fields() function to convert the dictionary of fields into the correct format for Firestore to use.

NOTE! this function will automatically update only those fields specified in the requests. This will help you update your document without overwriting the fields you don't specify in the request and don't want to touch.
For instance, if the document in this example was like this (before the update):

{
"name" : "A Name",
"active" : false,
"points" : 25,
"directory": { "path" : "a path" }
}

after the update it will look like this:

{
"name" : "Document Name",
"active" : true,
"points" : 25,
"directory": { "path" : "a path" }
}

Back


Delete A Document

Note you need to be authenticated and connected to a collection for this to work

.delete(documentId: String) -> FirestoreTask

The following will delete a new document in Firestore.

# 3.x
var del_task: FirestoreTask = firestore_collection.delete("DOCUMENT_ID")
var document: FirestoreDocument = yield(del_task, "task_finished")

# 4.x
var del_task: FirestoreTask = firestore_collection.delete("DOCUMENT_ID")
var document = await del_task.task_finished

Back


Issue a Query

Note you need to be authenticated for this to work

Firebase.Firestore.query(FirestoreQuery.new()) -> FirestoreTask

The following query retrieves some documents from a collection based on the value of a field.

# create a query
var query: FirestoreQuery = FirestoreQuery.new()

# FROM a collection
query.from("user_list")	

# WHERE points > 20
query.where("points", FirestoreQuery.OPERATOR.GREATER_THAN, 20)

# ORDER BY points, from the user with the best score to the latest
query.order_by("points", FirestoreQuery.DIRECTION.DESCENDING)

# LIMIT to the first 10 users
query.limit(10)

# Issue the query
var query_task: FirestoreTask = Firebase.Firestore.query(query)

# 3.x
# Yield on the request to get a result
var result: Array = yield(query_task, "task_finished")

# 4.x
var result: Array = await query_task.task_finished

Note: each FirestoreQuery function will always return itself, so the query component can be concatenated to create multi-line queries

# Do all the previous, but in one line
var query : FirestoreQuery = FirestoreQuery.new().from("user_list").where("points", FirestoreQuery.OPERATOR.GREATER_THAN, 20).order_by("points", FirestoreQuery.DIRECTION.DESCENDING).limit(10)

# 3.x
var result: Array = yield(Firebase.Firestore.query(query), "result_query")

# 4.x
var result: Array = await Firebase.Firestore.query(query).result_query

Back


Debugging

Note you need to be authenticated and connected to a collection for this to work

There are several signals that can be connected to for the purpose of debugging

  • Signal ("add_document", document)
  • Signal ("get_document", document)
  • Signal ("update_document", document)
  • Signal ("delete_document")
  • Signal ("error", bod.error.code, bod.error.status, bod.error.message)

These signals need to be connected to from the collection

# 3.x
firestore_collection.connect("add_document", self, "on_document_add")
firestore_collection.connect("get_document", self, "on_document_get")
firestore_collection.connect("update_document", self, "on_document_update")
firestore_collection.connect("delete_document", self, "on_document_delete")
firestore_collection.connect("error", self, "on_document_error")

# 4.x
firestore_collection.add_document.connect(on_document_add)
firestore_collection.get_document.connect(on_document_get)
firestore_collection.update_document.connect(on_document_update)
firestore_collection.delete_document.connect(on_document_delete)
firestore_collection.error.connect(on_document_error)

Back


Common Errors

Unauthorized

This occurs when you are trying to do something with a collection but have not logged in.

Back

Clone this wiki locally