> For the complete documentation index, see [llms.txt](https://estare.gitbook.io/firebase-auth-firestore-and-storage-plugin/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://estare.gitbook.io/firebase-auth-firestore-and-storage-plugin/plugin-elements/firestore-data-list.md).

# Firestore Data List

The Firestore Data List element can be used to fetch document data from Firestore as a list or  a count\*.&#x20;

{% hint style="info" %}
\*You can also use the [Firestore Data Aggregation](/firebase-auth-firestore-and-storage-plugin/plugin-elements/firestore-data-aggregation.md) element to get the count, sum or average of document's fields in a list
{% endhint %}

***

## <mark style="color:blue;">Settings</mark>

<div align="left"><figure><img src="/files/MaabKKi5UpFeUCIcLfBt" alt=""><figcaption></figcaption></figure></div>

### Firestore Collection

Here you must specify the id (name) of the collection, or the path to the subcollection you want to query data from (e.g. collection/doc\_id/subcollection).

The plugin will query data from the Firestore, running front-end process on Bubble. That way, no Workload units will be consumed. 🙂

### Query Type

* **List**\
  Performs a query for a list of documents from the Firestore Collection you've specified. It also applies the query and front-end filters defined on the element's settings.<br>
* **Count**\
  Performs a document count query from Firestore, respecting the query filters you defined.\
  Obs.: Each 1000 blocks of document accounted for will be billed as 1 document read on Firestore (e.g. 1500 documents counted will be billed for 2 reads).<br>
* **List and Count**\
  Performs both List and Count queries. That way you can use the "(list) documents data" and "(count) number of documents" state at once.

### Collection Group query

Sometimes, when using subcollection, we might want to query data across multiple subcollections at once. For instance, if you have a subcollection of reviews for a product, you might want to query all reviews from a supplier.

Collection Groups queries allows us to do that by providing the name/id of the collection/subcollection, making the query across every matching name collections.

So, if you check this option, the query will be performed on all collections and subcollection with the name/id you provided. For instance, the "reviews" collection, would look for every document below every "product" document.

{% hint style="warning" %}
Mind the names you give to your collections. If you have a collection named "reviews" and subcollections also named "reviews", the query will be performed on all levels, not only on subcollections.
{% endhint %}

### Make query static

If checked, document data won't update dynamically.

If left unchecked, queries will update responding to changes on the backend. Each document updated or removed from a list will account for a document read of Firebase's billing.

{% hint style="warning" %}
Count queries won't be dynamically updated. You'll have to run the [(count) update number of documents at a Firestore Data](#count-update-number-of-documents-at-a-firestore-data) action to update the count state.
{% endhint %}

### Query sort / order by options

<div align="left"><figure><img src="/files/IaMtQtIajSdeI594TGnD" alt=""><figcaption></figcaption></figure></div>

{% hint style="info" %}
This option only works with queries of type "List" or "List and Count".
{% endhint %}

You can choose a field to order your list of document from, at query level, specifying the sort direction (descending = yes | ascending = no).

When doing a sorted query for the first time, you might be confronted with an alert asking you to create an index for that query. That's a Firestore feature that creates different indexes for the database, which makes queries lighting fast.

To configure the new index, you need only access the link provided on the browser's console (press F12). After a couple of minutes, refresh the page and the query should work.

<div align="left"><figure><img src="/files/hdBp7gkA3Mlnv78QNaGC" alt=""><figcaption><p>Access the provided link to create the new index for the query.</p></figcaption></figure></div>

### Pagination

On the query sorting options, you can also specify a "Page Size" for the query, which allows you to work with pagination and can help you save document reads.

When you define a page size of 8, for instance, the query will only get the first 8 occurrences of the query you configured. That's why this option works only when you have a defined order for the data.

To change pages on the list, you can you the actions:

* show next page at a Firestore Data
* show previous page at a Firestore Data

{% hint style="warning" %}
Pagination on dynamic queries that on which the order of document's changes a lot may lead to unwanted behaviors, such as documents disappearing and returning only after you reload the page or the Firestore Data element. That's because of how pagination works on Firestore, as it uses other document's as reference for each page.

For instance, it you have 8 documents and one of them updates to the 9th position, since the next page starts at the current 10th document, this updated document might stay on a "limbo" in which it won't show unless you refresh the page or the Firestore Data element. This only happens if you had already loaded the 2nd page.
{% endhint %}

### Geoqueries (sort by location)

One common need for apps is to order data based on the geographic distance from a center. To help with that, this element provides fields to configure a Firestore Geoquery.

<div align="left"><figure><img src="/files/CrcQBXO95B7fDz3mlffq" alt=""><figcaption></figcaption></figure></div>

<table><thead><tr><th width="219">Field</th><th>Description</th></tr></thead><tbody><tr><td>is geohash</td><td>Check this field if the Query sort field is of type text/string an contain a "geohash" of a location. To generate a geohash, you can use the <a href="/pages/QR5E4yzUqlu7hgezmNw9">Firebase Geohash</a> element.</td></tr><tr><td>(geo) Center Latitude</td><td>Provide the latitude of the center of reference from which your data will be sorted.</td></tr><tr><td>(geo) Center Longitude</td><td>Provide the latitude of the center of reference from which your data will be sorted.</td></tr><tr><td>(geo) Distance from</td><td>The distance, im meters, from the center, that will be used to search for documents, according to the selected "query sort" field.</td></tr><tr><td>(geo) Geopoint field name</td><td>The name of the field of type <mark style="color:purple;">Geopoint</mark> on the document, that will be use to adjust the sorting from the furthest document to the closest one (<mark style="color:purple;">descending = "yes"</mark>) or from the closest to the furthest (<mark style="color:purple;">descending = "no"</mark>).</td></tr></tbody></table>

{% hint style="warning" %}
Geoqueries don't work with pagination, which means if you wish to display documents further from the center location, will have to do a new query, which might lead to more document reads and greater costs.
{% endhint %}

{% hint style="warning" %}
Limits on geoqueries are not precise. They limit the query from each quadrant of the search circle. So you can find yourself searching with a <mark style="color:purple;">limit = 1</mark> query, but reaceiving 3 or 4 documents, for instance.
{% endhint %}

### Query filters (list) (count)

{% hint style="info" %}
This settings work only with queries of type "List", "Count" or "List and Count".
{% endhint %}

This options allow you to choose fields from which to filter your query.

<div align="left"><figure><img src="/files/RZFiGrwUI1UtWCv4DRTg" alt=""><figcaption></figcaption></figure></div>

If you have security rules set to allow only the "owner" of a document to see it, for instance, you'll need to add a query filter to get only document's where the field "owner" equals the current user's reference.

You can choose to ignore empty constraints, which will simple "skip" the filter if the input you provided is empty. Keep in mind that in some cases this may require Firestore to create indexes for each filtering configuration.

#### Available query operators

You can read more on the [Cloud Firestore documentation](https://firebase.google.com/docs/firestore/query-data/queries#query_operators).

<div align="left"><figure><img src="/files/2dHQZM1QqYKueLkNhLDE" alt=""><figcaption><p>Query filter operators</p></figcaption></figure></div>

<table><thead><tr><th width="222">Operator</th><th>Description</th></tr></thead><tbody><tr><td>&#x3C;</td><td>Gets values less than the provided input (must be of type number or date)</td></tr><tr><td>&#x3C;=</td><td>Gets values less than or equal to the provided input (must be of type number or date)</td></tr><tr><td>==</td><td>Gets values equal to the provided input.</td></tr><tr><td>></td><td>Gets values greater than the provided input (must be of type number or date).</td></tr><tr><td>>=</td><td>Gets values greater than or equal to the provided input (must be of type number or date).</td></tr><tr><td>array-contains</td><td>Gets values where the field of type array/list has the value provided as input.</td></tr><tr><td>array-contains-any</td><td>Gets values where the field of type array/list any of the array of values provided as input.</td></tr><tr><td>in</td><td>Gets values where the field value is present on the array of values provided as input.</td></tr><tr><td>not-in</td><td>Gets values where the field value is not present on the array of values provided as input.</td></tr></tbody></table>

{% hint style="warning" %}
Firestore supports only one filter of type "array-contains", "array-contains-any", "in" or "not-in" per query. If you try to use more than one, the first one will be considered by the plugin, but the other's will be ignored.
{% endhint %}

{% hint style="warning" %}
Firestore does not offer "text" filters like the Bubble "contains keywords" option, because of the way they structure the database using indexes. For this kind os searches they recomend the use of external services like [Algolia](https://www.algolia.com/).
{% endhint %}

#### Types of filter values

Since Bubble is not flexible on the type of data we can define on plugins, the best way to implement our plugin was to work with texts. So each value you put on query values must be interpreted the right way to perform the Firestore Query. Defining a "query filter value type" can help us get it right.

So here are the types of query filter values:

<div align="left"><figure><img src="/files/gCrQtoIJvWUxIBvm2n8G" alt=""><figcaption><p>Query filter value types</p></figcaption></figure></div>

<table><thead><tr><th width="185">Type</th><th>How it will be handled</th></tr></thead><tbody><tr><td>auto</td><td>The plugin will try to infer the type from the input you provided.</td></tr><tr><td>text</td><td>Treated as a text value.</td></tr><tr><td>number</td><td>Treated as a number value.</td></tr><tr><td>boolean (true/false)</td><td>Treated as a true or false (yes/no) value.</td></tr><tr><td>date</td><td>Treated as a Date type. The plugin will convert the value to a Date.</td></tr><tr><td>array</td><td>Treated as a list in JavaScript format (e.g. ["item1", "item2", "item3"]).<br>If you need to use it on Bubble's lists, you can apply the ":format as text" message to the list, to build the array string into that format.</td></tr><tr><td>reference (coll/doc_id)</td><td>Treated as a document reference.<br>Document references are always handled by the plugin as paths to a document. For instance, if you want to get the reference for a document from the "tasks" collection with an id "1234", you should right "tasks/1234"</td></tr></tbody></table>

{% hint style="info" %}
Arrays and lists are always handled in JavaScript notation, which means each value should be comma separated and must be between brackets.

An array of number should be provided as a text like: \[1, 3, 45, 2]

An array of texts should contain balues between quotes: \["text1", "text2", "text3"]
{% endhint %}

{% hint style="info" %}
Document references are always handled by the plugin as paths to a document. For instance, if you want to get the reference for a document from the "tasks" collection with an id "1234", you should right "tasks/1234"
{% endhint %}

### Front-end sort (lists)

<div align="left"><figure><img src="/files/Rw612bXr1n8QuSAJnFPN" alt=""><figcaption></figcaption></figure></div>

Once data is fetched from Firestore, the plugin allows you to perform front-end operations without the need to query data again. This is ideal for performing fast sorting or filters as a reaction from input value changed on the user's UI.

To sort data, you must specify the name of the field, it's type and the direction (descending = yes | ascending = no). In most cases, you'll want to make the sort field be the same from the ["query sort" field](#query-sort-order-by-options-list).

### Front-end filters (lists)

<div align="left"><figure><img src="/files/C0yKdZSFSqjGQSiMhvRK" alt=""><figcaption></figcaption></figure> <figure><img src="/files/FElT6FGAEnEy7JF4btpE" alt=""><figcaption><p>Front-end filter types</p></figcaption></figure></div>

<table><thead><tr><th width="226">Comparison / Operator</th><th>Description</th></tr></thead><tbody><tr><td>==</td><td>Gets values equal to the provided input.</td></tr><tr><td>&#x3C;></td><td>Gets values not equal to the provided input.</td></tr><tr><td>>=</td><td>Gets values greater than or equal to the provided input (must be of type number or date).</td></tr><tr><td>></td><td>Gets values greater than the provided input (must be of type number or date).</td></tr><tr><td>&#x3C;=</td><td>Gets values less than or equal to the provided input (must be of type number or date)</td></tr><tr><td>&#x3C;</td><td>Gets values less than the provided input (must be of type number or date)</td></tr><tr><td>contains</td><td>Gets values where the field of type array/list has the value provided as input.</td></tr><tr><td>contains-any</td><td>Gets values where the field of type array/list has any of the array of values provided as input.</td></tr><tr><td>contains case sensitive</td><td>Gets values where the field of type array/list has the value provided as input, but differentiating uppercase from lowercase characters.</td></tr><tr><td>doesn't contain</td><td>Gets values where the field of type array/list doesn't have the value provided as input.</td></tr><tr><td>doesn't contain case sensitive</td><td>Gets values where the field of type array/list doesn't have the value provided as input, but differentiating from uppercase and lowercase characters.</td></tr><tr><td>is in</td><td>Gets values where the field value is present on the array of values provided as input.</td></tr><tr><td>isn't in</td><td>Gets values where the field value is not present on the array of values provided as input.</td></tr><tr><td>isn't empty / count > 0</td><td>Gets values where the field value doesn't exist, is empty or, if it's an array/list, its length is zero.</td></tr><tr><td>is empty / count = 0</td><td>Gets values where the field value exists, is not empty or, if it's an array/list, its length is greater than zero.</td></tr></tbody></table>

### Extract fields from a list of documents

<div align="left"><figure><img src="/files/GbVvtfFXO0OTW9hRNkZW" alt=""><figcaption></figcaption></figure></div>

You can provide the names of the fields on the list of document's you'd like to get as a list on Bubble.&#x20;

{% hint style="info" %}
You can you "dot notation" to dive into the JSON structure of a Map field in a document (e.g. address.street to get the "street" property of the "address" field, if it is a Map type)
{% endhint %}

#### Field types

For each field you choose to fetch from the document, you must specify the type of data Bubble should try to receive.&#x20;

In some cases, more than one type can be applied, like in boolean values, that you can get as "text" or "yes/no". In other cases you must be careful to declare the right value, or error can occur, like when you try to declare a "number" for a "text" value.

#### Get list inside field

This option allows you to merge fields of type list in one single list.&#x20;

For instance, if you have two documents with a field named "tags", that has a list of texts (one \["tag1"] and the other \["tag1", "tag2]), this option will merge them as \["tag1", "tag1", "tag2"] instead of bringing two array values as texts (i.e. \["tag1"], \["tag1", "tag2"]).

#### Ignore filters

This option will make the list of values ignore the front-end filters applied to them.

This is useful when you want to use this list to feed the choices source of a Dropdown or input that you want to use as a front-end filter. If you leave this option unchecked, the choices sorce would be filtered too.

***

## <mark style="color:blue;">States and Values</mark>

The Firestore Data List element provides states according to the query type you chose on it's settings.

<div align="left"><figure><img src="/files/Cr6PYWBzcmHQRFkbTeBF" alt=""><figcaption></figcaption></figure></div>

### Data list

A list of document JSON strings, that can be provided to repeating groups and then, on each cell, extracted through a [Firestore Data Extractor](/firebase-auth-firestore-and-storage-plugin/plugin-elements/firestore-data-extractor.md) to get the values from the document fields.

### Data list (w/ schema)

A list of documents, interpreted through the "data schema" you define on an API Connector and provide to the element. See how to configure this on the [Data Schemas](/firebase-auth-firestore-and-storage-plugin/plugin-elements/data-schemas.md) documentation.

### Collection

The name of the collection from which the element is getting it's data from.

### Error message

If the query fails and returns an error, the error message will be stored on this state.

### Documents ids (list)

A list of texts contains the IDs of the document fetched from a "List" or "List and Count" type of queries.

### Fields Lists (1, 2, 3...)

Lists of fields you chose to retrieve from the documents list, with filters already applied.

### Data is Ready

Turns to "yes" when all the element's states are done being filled, an "no" when they are being filled.

Although this operations are fast, the fact the they are filled in order and not at the same time may lead to issues, that's why this state was created.

***

## <mark style="color:blue;">Element Actions</mark>

<div align="left"><figure><img src="/files/CkhYJRWdq6Qofaf8lhro" alt=""><figcaption></figcaption></figure></div>

### Refresh (list)

This action reloads the elements data, performing queries again. This might be useful to provide consistency in your data.

### Update number of documents (count)

This action allows you to add, remove or refresh the count query of a Firestore Data element.

{% hint style="info" %}
Tip: Sometimes you now exactly how the count will change, like when a user adds a new task to his/her list, you know it will increment in 1, so you don't need to perform the query again, saving some document reads.
{% endhint %}

<div><figure><img src="/files/VZGw7mZ0FGiG58kcsuiZ" alt=""><figcaption></figcaption></figure> <figure><img src="/files/Byn7cNIos7Epqe9NEPyF" alt=""><figcaption><p>Count update options.</p></figcaption></figure></div>

### Update a document entry (static)

On static queries, though we don't need to have them listen for changes all the time, updating a single document on it might be needed sometimes. Because of that we provide this update action for you to specify a document id that will be fetched again from Firestore and will substitute the current entry on the static query.

That helps to avoid an enteire refresh of the query, saving document reads and fetching a single document instead of a list.

<figure><img src="/files/XkU9VWDInHfEzYA7YfqQ" alt=""><figcaption></figcaption></figure>

### Show next page (list)

When you have a defined page size, this action queries the next set of documents of the query, according to the page size you set, displaying them on the ["document data" state](#document-data-single).

### Show previous page (list)

When you have a defined page size, this action get the previous set of documents of the query.&#x20;

This won't make another query. Since the document were already available on the front-end, the plugin stores them to display them again as needed. If you which to update any entry on the document list already fetched, you can use the [update document entry](#update-a-document-entry-static) action.

***

## <mark style="color:blue;">Events</mark>

### Data ready or changed

<div align="left"><figure><img src="/files/wjeYBulyF83IVboE08m1" alt=""><figcaption></figcaption></figure></div>

This event is triggered when the data from the query is ready, or when new data arrives in a dynamic query.

{% hint style="warning" %}
Each document updated in a dynamic query accounts trigges the event, so if you have, for instance, 3 quick updates, the event will be triggeres 3 times.
{% endhint %}

***

## <mark style="color:blue;">Using query results as inputs in other queries</mark>

Keep in mind that, because the query operations run on the front-end, Bubble sometimes messes with the order in which data arrives from Firestore. That means you must account that factor while using results of other Firebase elements as input data in other query elements.

For instance, if you want to get documents form the "tasks" collection where the "owner" filter equals the current user's document reference, you can use the filter bellow (owner == users/Firebase Auth's User ID).

<div align="left"><figure><img src="/files/nPBkufqRvx50zAgEmRag" alt=""><figcaption></figcaption></figure></div>

But if the User ID is not yet available, the query will fail due to security rules on Firestore.

To work around that, you can put a visibility conditional on the Firestore Data element, for it to show only when the User ID is not empty. As the query will only occur when the element is "visible" on the page, it will wait for when the User ID is available to run the query, avoiding the error.

<div align="left"><figure><img src="/files/rZPXAQdxnlsPRRT75Kid" alt=""><figcaption></figcaption></figure> <figure><img src="/files/zId6dG87hXfABVNNSvuE" alt=""><figcaption></figcaption></figure></div>

Keep that in mind when fetching data from Firestore.
