Firestore structured query search by document id - firebase

I'm trying to query a firestore collection by document id but not using firestore CLI but rather a structured query (because I'm using Zapier to automate some workflows). Is there a way to search by documented as the field? So far I've tried the below code and variations where I replace name with "documentId()", "documentId" and nothing seems to work. When I use name I get the following error:
"error":
"code": 400,
"message": "key filter value must be a Key",
"status": "INVALID_ARGUMENT"
"where": {
"fieldFilter": {
"field": {
"fieldPath": "__name__"
},
"op": "EQUAL",
"value": {
"stringValue": "THE ID I WANT TO LOOK FOR"
}
}
}

If you want to get a document by id using __name__, change the value type to referenceValue and provide the full path to the document instead of just the id for the query.
"where": {
"fieldFilter": {
"field": {
"fieldPath": "__name__"
},
"op": "EQUAL",
"value": {
"referenceValue": "projects/project_id/databases/database_id/documents/your_collection/doc_id"
}
}
}

Assuming that you want to get a specific document using a document id. You may want to refer to the code below:
axios.get(`https://firestore.googleapis.com/v1/projects/<Project-ID>/databases/(default)/documents/<Collection-Name>/<Document-ID>`)
.then(res => {
console.log(res);
})
.catch(error => {
console.log(error);
});
The code above will get a specific document that you want. If you want to get a document ID with a specific value of its field, then this line here: "fieldPath": "__name__" should be a fieldName not a document id. "fieldPath": "<FieldName>". and also, make sure the method you're using is POST. See code sample below for reference:
axios.post(`https://firestore.googleapis.com/v1/projects/<Project-ID>/databases/(default)/documents:runQuery`,
{
"structuredQuery": {
"from": [{
"collectionId": "<Collection-Name>"
}],
"where": {
"fieldFilter": {
"field": {
"fieldPath": "<FieldName>"
},
"op": "EQUAL",
"value": {
stringValue: "<FieldValue>"
}
}
}
}
}).then(res => {
console.log(res)
})
.catch(error => {
console.log(error)
})
All the codes above are for reference only which I used axios for fetching the data from Firestore.
For more information, checkout this documentation.

Related

How to make a post request with a custom token document ref with firebase firestore Rest API

Here is my code below, I'm trying to send a post request using Firebase Firestore Rest API. It works, but it generates a random ref id token that links it to the post data (fields) I sent, which makes it difficult to relate to.
I want to be able to link my post data with a custom id token.
final String customIdToken9 = 'customIdToken9'
String url = "https://firestore.googleapis.com/v1/projects/myAppId/databases/(default)/documents/customers/$customIdToken9"
const _body = {
"fields": {
"androidNotificationToken": {
"nullValue": null
},
"fullname": {
"stringValue": "Custom"
},
"uid": {
"stringValue": "$customIdToken9"
},
"admin": {
"stringValue": ""
},
"email": {
"stringValue": "customer1#gmail.com"
},
"photo": {
"stringValue": ""
},
"coverPhoto": {
"stringValue": ""
},
"bio": {
"stringValue": ""
},
"role": {
"stringValue": "user"
},
"mobile": {
"stringValue": "092222"
}
}
}
http.post(url, body = _body);
When I run this code above it returns
{
"error": {
"code": 400,
"message": "Document parent name \"projects/MyAppId/databases/(default)/documents/customers\" lacks \"/\" at index 59.",
"status": "INVALID_ARGUMENT"
}
}
If I remove the customTokenId9, it works, but it generates a random token Id, which I don't want
String url = "https://firestore.googleapis.com/v1/projects/myAppId/databases/(default)/documents/customers/"
http.post(url, body = _body);
If you want to specify your own document name, you need to add a query paramater called documentId to your URL request. Here's how it should look like on your code:
final String customIdToken9 = 'customIdToken9'
String url = "https://firestore.googleapis.com/v1/projects/myAppId/databases/(default)/documents/customers?documentId=$customIdToken9"
const _body = {
"fields": {
"androidNotificationToken": {
"nullValue": null
},
"fullname": {
"stringValue": "Custom"
},
"uid": {
"stringValue": "$customIdToken9"
},
...
}
}
The client-assigned document ID to use for creating a document. It is optional. If not specified, a random ID will automatically be assigned by the service.
Full description is stated in this link and you'll see it in the Query Parameters section. You can also try to test out the API and expand it to see its curl equivalent.
Additionally, you can look up to this documentation to understand how a query parameter works. It applies on any REST API's offered by Firebase.
Why is your variable final String customIdToken but you are using $customIdToken9 it should be $customIdToken.

How to retrieve firebase documents missing a field using runQuery and the IN operator?

This is my http POST requst body...
{
"structuredQuery": {
"select": {
"fields": [
{
"fieldPath": "name"
},
{
"fieldPath": "taxId"
},
{
"fieldPath": "mailingAddress"
}
]
},
"from": [
{
"collectionId": "orgs"
}
],
"where": {
"fieldFilter": {
"field": {
"fieldPath": "orgId"
},
"op": "IN",
"value": {
"arrayValue": {
"values": [
{
"stringValue": ""
},
{
"nullValue": null
}
]
}
}
}
}
}
It fails to return orgs where the orgId field is completely missing from the document. It correctly includes orgs where the orgId field is present and equal to empty string. This is accessing a Cloud Firestore db.
Due to the way Firestore indexes data, it is not possible to query for documents for which a certain field "is completely missing from the document": the field needs to exist in order for the Firestore index to take it into account. More details on the indexing mechanism in the following official video.
You may store an empty value in this field, as you mention in your question.

Firestore RESTful API Query only returns readTime as payload

I am running the following POSTrequest (GET won't work, if anyone was trying and landed here):
URL: https://firestore.googleapis.com/v1/projects/{{ firebaseProjectID }}/databases/(default)/documents:runQuery
The JSON payload I send:
{
"structuredQuery": {
"from": [
{
"collectionId": "items"
}
],
"where": {
"fieldFilter": {
"field": {
"fieldPath": "inStock"
},
"op": "EQUAL",
"value": {
"booleanValue": true
}
}
}
}
}
I receive the following in return:
[
{
"readTime": "2020-04-19T19:38:00.808564Z"
}
]
Why do I receive not a list of documents? I certainly have matching documents.
I should receive all fields given that I entered no list of fields:
https://firebase.google.com/docs/firestore/reference/rest/v1/StructuredQuery#Projection
Posting as Community Wiki, due to the talk that occurred in the comments of the question.
As discussed in the comments, between #RenaudTarnec and #Spurious, it seems that the problem was related to the path in the URL. Once it was corrected - might be related to the "allDescendants": true, but it should not - the call worked and returned the values as expected.

Firebase Firestore REST Request - Query and Filter

I have a firestore database on a firebase project. I want to make rest request for filtering or querying data with postman. I'm using "https://firestore.googleapis.com/v1/projects//databases/(default)/documents/" to get the data in a known path in my database. Here is a sample of my database structure:
users > xxxxx > messages > yyyyy> "sent":"true"
where "users" and "messages" are collections, "xxxxx" and "yyyyy"are autogenerated document ids (xxxxx is autogenerated user id)
What I want to do is to find the "xxxxx"s (users) which have >"sent":"true"< data.
I get success if I know the "xxxxx" and "yyyyy" but I don't know them because they are autogenerated and different from each other in my database and don't know how to do it.
You need to run a Query, as explained here in the documentation of the REST API.
Since you want to query all the messages sub-collections of different user documents, you need to "simulate" a Collection Group Query in your StructuredQuery. The way to do that is to set the allDescendants element to true in the CollectionSelector.
So, issuing a POST HTTP Request on the following URL will do the trick:
var URL = "https://firestore.googleapis.com/v1/projects/<your-project-id>/databases/(default)/documents:runQuery";
The body of the POST Request shall contain:
"structuredQuery": {
"from": [{
"collectionId": "messages",
"allDescendants": true
}],
"where": {
"fieldFilter": {
"field": {
"fieldPath": "sent"
},
"op": "EQUAL",
"value": {
"stringValue": "true",
}
}
}
}
Note that you need to add a single field index to your Firestore DB, as follows:
Note also that, if your field sent is of type Boolean (and not String as shown in your question), you need to use a booleanValue element in your Value JSON element.
I am unable to get this to work for some reason.
I have a Collection called dzs which has some documents with auto generated id's.
I want to query and find a document with a specific email address.
When I try this in Postman, it returns (Error 400 Bad request)
"structuredQuery": {
"from": [{
"collectionId": "dzs",
"allDescendants": true
}],
"where": {
"fieldFilter": {
"field": {
"fieldPath": "email"
},
"op": "EQUAL",
"value": {
"stringValue": "123#123.com",
}
}
}
}
Add the parent collection/document path to the URL:
var URL = "https://firestore.googleapis.com/v1/projects/<your-project-id>/databases/(default)/documents/users/xxxxx:runQuery";
Then make the collectionId "messages" and allDescendents false:
"structuredQuery": {
"from": [{
"collectionId": "messages",
"allDescendants": false
}],
"where": {
"fieldFilter": {
"field": {
"fieldPath": "sent"
},
"op": "EQUAL",
"value": {
"stringValue": "true",
}
}
}
}
Source

How should a "write" request be structured for Firestore REST API (v1beta1)?

Based on the Google Discovery document, and RPC reference, it appears that the :write resource should be available for Firestore database interactions, but performing such a request to my (POST https://firestore.googleapis.com/v1beta1/projects/[my project]/databases/(default)/documents:write) results in:
[
{
"error": {
"code": 400,
"message": "Invalid value (Object), ",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"description": "Invalid value (Object), "
}
]
}
]
}
}
]
Is this possible? A related SO answer alludes to this being available as a means of field transforms, the same reason I require this, but I cannot construct valid a JSON body to succeed in the request. Currently, variations on the following don't work as expected when trying a minimum successful response:
{
"writes": [
{
"update": {
"name": "projects/{projectId}/databases/[my project]/documents/exampleId",
"fields": {
"example": {
"integerValue": 100
},
"timestamp": {
"nullValue": null
}
},
"transform": {
"document": "projects/[my project]]/databases/(default)/documents/examples/exampleId",
"fieldTransforms": [
{
"fieldPath": "timestamp",
"setToServerValue": "REQUEST_TIME"
}
]
}
}
}
]
}
First of all, note that you should use the v1 version of the REST API, not the betas.
To create a document, you would use the createDocument method, while to update a document you would use the patch one.
For the document creation you should therefore make a POST HTTP Request to the following URL
https://firestore.googleapis.com/v1/projects/<your-project-id>/databases/(default)/documents/<the-desired-collection>
with the following Request body:
{
fields: {
example: {
integerValue: 100
}
}
}
You need to use documents:commit instead of documents:write
also the name field should be in this format:
"name": "projects/projectID/databases/(default)/documents/collectionName/DocumentId"
See this post.

Resources