My .indexOn rule added to Security & Rules isn't taken into account - firebase

I'm trying to set up custom indexes on my firebase data for sorting on certain fields.
Here is my data:
GET https://testindexon.firebaseio.com/.json
{
"key1": {
"age": 80,
"name": "zabc"
},
"key2": {
"age": 90,
"name": "defg"
},
"key3": {
"age": 10,
"name": "hijk"
}
}
Here are my security rules:
{
"rules": {
".read": true,
".write": true,
"testindexon": {
".indexOn": "age"
}
}
}
When I try to orderBy the indexed "age" property, I get an error:
GET https://testindexon.firebaseio.com/.json?orderBy="age"
Error 400 (Bad request)
{
"error": "Index not defined"
}
I can get around the 400 Error by rewriting my security rules as follows:
{
"rules": {
".read": true,
".write": true,
".indexOn": ["age", "name"]
}
}
But then when I try to order by one of the properties, nothing special happens (results aren't sorted):
GET ....firebaseio.com/.json?orderBy="age"
{
"key1": {
"age": 80,
"name": "zabc"
},
"key2": {
"age": 90,
"name": "defg"
},
"key3": {
"age": 10,
"name": "hijk"
}
}
Am I missing something ? I would appreciate any help.
Best,
State variable

According to the Firebase documentation on retrieving data through its REST API:
THE REST API RETURNS UNSORTED RESULTS
JSON interpreters do not enforce any ordering on the result set. While orderBy can be used in combination with startAt, endAt, limitToFirst, or limitToLast to return a subset of the data, the returned results will not be sorted. Therefore, it may be necessary to manually sort the results if ordering is important.
There are indeed samples and others fragments in that documentation that seem to suggest otherwise. But the above statement is true.
Keep in mind that the orderBy parameter is used for more things than just returning ordered results. You'd also use the method to filter the results, i.e.
GET 'https://testindexon.firebaseio.com/.json?orderBy="age"&equalTo=90'
Or you would order to return a limited number of results:
GET 'https://testindexon.firebaseio.com/.json?orderBy="age"&limitToFirst=10'
So in these cases, the child nodes are sorted on the server and then filtered, but the return value will/may still contain the remaining child nodes in an undetermined order.

It looks to me like your .indexOn is on the wrong path. You're fetching root, but put the .indexOn under the child path testindexon/. Thus, your URL would need to be https://testindexon.firebaseio.com/testindexon/.json in order to take advantage of the orderBy.

Related

How can document references be used for Firestore API's [runQuery.startAt]?

When using the Firestore REST API to order and filter results, I am unable to use a cursor/reference value for the startAt value. I feel this may be possible, seeing it is provided in examples of Firestore's cursor-based pagination is detailed in their SDK: https://firebase.google.com/docs/firestore/query-data/query-cursors
I have a query that uses orderBy on a integer field within a document. I can successfully start at a specific integer value for this query, like so:
"structuredQuery": {
"from": [
{
"collectionId": "objects"
}
],
"orderBy": [
{
"field": {
"fieldPath": "counter"
},
"direction": "DESCENDING"
}
],
"startAt": {
"values": [
{
"integerValue": 15
}
]
}
}
I'm hoping to benefit from cursor pagination, but unfortunately if I change the startAt value to referenceValue, the query results do not reflect this, even though the query is successfully performed.
"startAt": {
"values": [
{
"referenceValue": "projects/.../databases/(default)/documents/objects/OjvmBvvQ9TkyyQiJ4ExJ"
}
]
}
Am I missing something in the way this works differently to the SDK examples?
Note that it's not a document reference but a document snapshot that you can use as a query cursor. A snapshot includes the field values needed for startAt. The SDKs take a document snapshot, extract the field values, and pass those values to startAt.
You can see the Node.js client library doing this here in createCursor and extractFieldValues.

Query nested object in Firestore REST API

I'm stuck with querying Firestore REST API. I can figure out how to filter by a regular key but I can't figure out how to query by nested object key.
Basically, in the browser client, I can do
firestore.collection("channels")
.where("members.[memberID]", "==", true)
.get()
However, when I try to do the same in the REST API, it said Invalid Argument. I was trying to do
{
"structuredQuery": {
"where": {
"fieldFilter": {
"field": {
"fieldPath": "members.[memberID]"
},
"op": "EQUAL",
"value": {
booleanValue: "true"
}
}
},
"from": [
{
"collectionId": "channels"
}
]
}
}
but it gives me "Invalid Argument" error on fieldPath. Does anybody know how to query Firestore REST API based on nested object?
Thank you!
I asked for Firebase support and they said special characters in fieldPath such as "-" in my case can be escaped using back tick or back slash. It is mentioned in the documentation. In my case, I'll need to do
members.`[memberID]`
I hope this is helpful for you guys.

Filtering Firebase lists based nested child keys?

In the Firebase docs for Structuring Data, they give the follow data structure as an example of mapping users to groups.
{
"users": {
"alovelace": {
"name": "Ada Lovelace",
// Index Ada's groups in her profile
"groups": {
// the value here doesn't matter, just that the key exists
"techpioneers": true,
"womentechmakers": true
}
},
...
},
"groups": {
"techpioneers": {
"name": "Historical Tech Pioneers",
"members": {
"alovelace": true,
"ghopper": true,
"eclarke": true
}
},
...
}
}
With that structure, how would I go about querying only groups with a specific member? So only groups where alovelace is a member, for example.
Would I do this with a rule? If so, what would that rule look like?
OrderByChild works in this case - below the query object
angularfire.database.list('.../groups', {
query: {
orderByChild: 'members/alovelace'+,
startAt: true
}
});
Not sure how the performance is compared to the answer by Frank van Puffelen - might be worse even since it's another list query rather than just a few direct object lookups.
That information is already in the data model. Right under /users/alovelace/groups you have a list of the groups she's a member off.
The reason for recommending this model is that it doesn't even require a query to load the list of groups, it just requires a direct-access read of /users/alovelace/groups.

firebase: my dinosaurs are not ordered by height [duplicate]

I'm trying to set up custom indexes on my firebase data for sorting on certain fields.
Here is my data:
GET https://testindexon.firebaseio.com/.json
{
"key1": {
"age": 80,
"name": "zabc"
},
"key2": {
"age": 90,
"name": "defg"
},
"key3": {
"age": 10,
"name": "hijk"
}
}
Here are my security rules:
{
"rules": {
".read": true,
".write": true,
"testindexon": {
".indexOn": "age"
}
}
}
When I try to orderBy the indexed "age" property, I get an error:
GET https://testindexon.firebaseio.com/.json?orderBy="age"
Error 400 (Bad request)
{
"error": "Index not defined"
}
I can get around the 400 Error by rewriting my security rules as follows:
{
"rules": {
".read": true,
".write": true,
".indexOn": ["age", "name"]
}
}
But then when I try to order by one of the properties, nothing special happens (results aren't sorted):
GET ....firebaseio.com/.json?orderBy="age"
{
"key1": {
"age": 80,
"name": "zabc"
},
"key2": {
"age": 90,
"name": "defg"
},
"key3": {
"age": 10,
"name": "hijk"
}
}
Am I missing something ? I would appreciate any help.
Best,
State variable
According to the Firebase documentation on retrieving data through its REST API:
THE REST API RETURNS UNSORTED RESULTS
JSON interpreters do not enforce any ordering on the result set. While orderBy can be used in combination with startAt, endAt, limitToFirst, or limitToLast to return a subset of the data, the returned results will not be sorted. Therefore, it may be necessary to manually sort the results if ordering is important.
There are indeed samples and others fragments in that documentation that seem to suggest otherwise. But the above statement is true.
Keep in mind that the orderBy parameter is used for more things than just returning ordered results. You'd also use the method to filter the results, i.e.
GET 'https://testindexon.firebaseio.com/.json?orderBy="age"&equalTo=90'
Or you would order to return a limited number of results:
GET 'https://testindexon.firebaseio.com/.json?orderBy="age"&limitToFirst=10'
So in these cases, the child nodes are sorted on the server and then filtered, but the return value will/may still contain the remaining child nodes in an undetermined order.
It looks to me like your .indexOn is on the wrong path. You're fetching root, but put the .indexOn under the child path testindexon/. Thus, your URL would need to be https://testindexon.firebaseio.com/testindexon/.json in order to take advantage of the orderBy.

Limit depth of data returned

Is it possible to limit the depth of data returned from Firebase database?
For example, if I want to get some data from a parent object without waiting for all of its children & sub-children, can I specify that I only want x levels of objects?
Firebase does not yet have this capability.
We do intend to add it, but don't have a timetable yet.
There appears to be a shallow option...
{
"message": {
"user": {
"name": "Chris"
},
"body": "Hello!"
}
}
// A request to /message.json?shallow=true
// would return the following:
{
"user": true,
"body": true
}
// A request to /message/body.json?shallow=true
// would simply return:
"Hello!"
From: https://firebase.google.com/docs/database/rest/retrieve-data

Resources