Firestore integration: How to query by field

I have been trying to integrate Google Firestore using the data configurator with mixed success (see my other post: Rest API for Google Firestore).

I would appreciate any help with querying the database by field. The following curl request works fine in the Firestore API Explorer:

curl --request POST
https://firestore.googleapis.com/v1/projects/{databaseId}/databases/(default)/documents/./:runQuery
–header ‘Accept: application/json’
–header ‘Content-Type: application/json’
–data ‘{“structuredQuery”:{“select”:{“fields”:[{“fieldPath”:“nameInm”},{“fieldPath”:“nicInm”}]},“from”:[{“collectionId”:“Inmueble”,“allDescendants”:true}],“where”:{“fieldFilter”:{“field”:{“fieldPath”:“nameInm”},“op”:“EQUAL”,“value”:{“stringValue”:“Bloquera 1”}}}}}’
–compressed

The response (JSON) is:

[{
“document”: {
“name”: “projects/{databaseId}/databases/(default)/documents/Inmueble/wMQ1E5udqnJ9SvZyzcJU”,
“fields”: {
“nicInm”: {“stringValue”: “17-00-00-00312”},
“nameInm”: {“stringValue”: “Bloquera 1”}
},
“createTime”: “2020-04-14T23:37:38.787273Z”,
“updateTime”: “2020-04-14T23:37:38.787273Z”
},
“readTime”: “2020-04-21T12:40:44.591196Z”
}]

The problem is that I can’t get to configure the data configurator in Composer Pro to send the correct call.

Could you take a screenshot of your REST API configuration in Composer Data Configurator? The correct place to configure the payload is under POST request body on the Schema tab.

However, considering that the query object seems to be highly dynamic, you might want to consider using just the HTTP request flow function, copypasting your query as a formula in the Request body field

{"structuredQuery":{"select":{"fields":[{"fieldPath":"nameInm"},{"fieldPath":"nicInm"}]},"from":[{"collectionId":"Inmueble","allDescendants":true}],"where":{"fieldFilter":{"field":{"fieldPath":"nameInm"},"op":"EQUAL","value":{"stringValue":"Bloquera 1"}}}}}

and then if needed, wrapping the whole thing with a custom flow function so you can define the proper schema for the response. Would that approach make more sense?

If I read correctly, you figured this out in REST API for Google Firestore Tutorial right?

The request schema at least needs to be an object with identical format to the JSON payload, not a string like in your screenshot.

Not yet. I get it to work on some instances, but not in others. The request schema seems to change depending on the query, which is highly inconvenient. I’m trying to find out what are the rules for a working schema, because up to now it’s trial and error. One thing is for sure, the GET schema is not accepted on the other http calls, as the GET schema includes information that Firestore sets by itself and can not be passed on the request.
I get a query by record (document) id without problem, as stated on the tutorial post. Once I figure out the rules for a query by field I will edit the post to include this kind of call, because it is much more useful.

All right! Note that if there are fields that are dynamic, you can edit the schema manually to make it e.g. just an “object” instead of object with specific properties. This will mean the user must know the structure and use formula functions “blindly” to access it, but this is one (hacky) way to support dynamic schemas in REST APIs.

Hi Harri,

I got the query to work in Test setting the POST request schema to the structuredQuery required by Firestore


and the response schema from it.
image
However, I have been unable to use the response data because I can not find where is it available.

I feel I am almost there getting Firestore Cloud to work (got every thing else: GET, GETALL, DELETE, POST) and would really appreciate your help with this.

Forgot, I find the response on the options for setting the data variable, but the data is not available:


The actual data is under “Query Inmuebles Asociados / Response:document.fields.nombInmueble.stringValue”, which is not an available option

That’s a mismatched type, so changing the schema of the .stringValue field to match the target binding schema should work. If you know internally that the data will match, you can also always use formulas for the binding – it will complain about mismatched schema but execute the binding regardless.

Thanks Harry, I used a formula to assign the response values to a variable and it worked. Now is clear how to query Firestore by fields. I have the full tutorial ready now.

1 Like

Eduardo, maybe slightly off topic, but can you explain to a new user why they’d want/need to use Firestore above and beyond the data store provided with AppGyver?

Like clearly keeping your data outside of a single solution is a big one, so if AG ever disappeared then you’d at least still have your data.

Are there also technical reasons, like projects that can’t be built with the internal data store?

Firestore is a non relational (NoSQL) database. As such, it is ideal for data that in someway, or for some reason, needs redundancy or the redundancy is inherent to it, be it structured or not (ie. documents).

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”

What I find special, besides the aforementioned and it being easy to setup, is that it has a free usage policy for low traffic use (as of july 1, 2020, it’s free up to 50.000 reads/day, 20.000 writes/day and 20.000 deletes/day) that allows its free use for many applications and, if needed, growth is not a problem.

Hi Eduardo, i’m new in appgyver and i have same problem to que data from firestore and filter by field.

I don’t understand very well your solution, do you have a doc ou screenshot step by step how can solve this problem.

Thank you very much!
Wendell

1 Like

Hi Wendell,

There is a tutorial with step by step on the setup of Firebase at https://docs.appgyver.com/appgyver-academy/tutorials/tutorial-articles/google-firestore-rest-api-integration that has what you are looking for

Regards,

Eduardo

Can you share tour formula as sample to see how do you put the data in thé variable ??

Hi @Eduardo_Jaramillo , @Harri_Sarsa

Can you please help me with this problem?

I am so close but not done yet. I have the response object but cant read it in any way

Hi Harri,

Can you share the schema?

Eduardo

What formula did you use in Set Data Variable component?

UPDATE:
Hello everyone, my issue is solved and I can now populate the runQuery data into the page variable. Want to share my learning with the community.

The URL I’s using in the Firebase API explorer was
https://firestore.googleapis.com/v1/projects/xxxxxx/databases/(default)/documents/*/:runQuery
Without the slashes and a dot in between after /documents, the EXECUTE button in the API Explorer was not enabled. However it worked in Postman with the following url:
https://firestore.googleapis.com/v1/projects/xxxxxx/databases/(default)/documents:runQuery
Hope this is useful for a lot of folks trying out the Create Record component to fetch queried list in Firestore collections.
UPDATE END

Hi, trying to do the same thing but unfortunately not successful at the API Explorer stage itself. Any help would be highly appreciated. I know you guys are busy like crazy but tagging the ever helpful
@Harri_Sarsa, @Mari and @Mevi Here is my curl and the response error:

curl --request POST
https://firestore.googleapis.com/v1beta1/projects/xxxxx/databases/(default)/documents/./runQuery:runQuery?key=[YOUR_API_KEY]
–header ‘Authorization: Bearer [YOUR_ACCESS_TOKEN]’
–header ‘Accept: application/json’
–header ‘Content-Type: application/json’
–data ‘{“structuredQuery”:{“select”:{“fields”:[{“fieldPath”:“contentType”}]},“from”:[{“collectionId”:“UserContent”}],“where”:{“fieldFilter”:{“field”:{“fieldPath”:“contentType”},“op”:“EQUAL”,“value”:{“stringValue”:“reply”}}}}}’
–compressed

Response:
{
“error”: {
“code”: 400,
“message”: “Invalid JSON payload received. Unknown name “structuredQuery” at ‘document’: Cannot find field.”,
“status”: “INVALID_ARGUMENT”,
“details”: [
{
@type”: “type.googleapis.com/google.rpc.BadRequest”,
“fieldViolations”: [
{
“field”: “document”,
“description”: “Invalid JSON payload received. Unknown name “structuredQuery” at ‘document’: Cannot find field.”
}
]
}
]
}
}