If I insert data into node/a/0
in firebase.
the result will treat a
is an array a[0]
.
The same way, if I set my data in
Workaround for REST API: add a meaningless filter like this one orderBy="$.key"&startAt="0"
which actually filters-out all items with negative key): https://workaround-arrays-bagohack.firebaseio.com/matchesHeuristic.json?orderBy=%22$key%22&startAt=%220%22&print=pretty
This is a known and unfortunate (IMHO) behaviour of Firebase, documented deep down in their support knowledge base. Quote from Best Practices: Arrays in Firebase:
Firebase has no native support for arrays. If you store an array, it really gets stored as an "object" with integers as the key names.
// we send this
['hello', 'world']
// Firebase stores this
{0:'hello', 1: 'world'}
However, to help people that are storing arrays in Firebase, when you call
.val()
or use the REST api to read data, if the data looks like an array, Firebase will render it as an array.In particular, *if all of the keys are integers, and more than half of the keys between 0 and the maximum key in the object have non-empty values, then Firebase will render it as an array. This latter part is important to keep in mind.
You can't currently change or prevent this behavior. Hopefully understanding it will make it easier to see what one can and can't do when storing array-like data.
So I've set up a small repro for you. Original data:
{
"matchesHeuristic": {
"1": {
"id": "foo",
"value": "bar"
},
"2": {
"id": "w",
"value": "tf"
}
},
"notMatchesHeuristic": {
"1": {
"id": "foo",
"value": "bar"
},
"365": {
"id": "w",
"value": "tf"
}
}
}
As returned by Firebase REST API: https://workaround-arrays-bagohack.firebaseio.com/.json?print=pretty
{
"matchesHeuristic" : [ null, {
"id" : "foo",
"value" : "bar"
}, {
"id" : "w",
"value" : "tf"
} ],
"notMatchesHeuristic" : {
"1" : {
"id" : "foo",
"value" : "bar"
},
"365" : {
"id" : "w",
"value" : "tf"
}
}
}
as you can see matchesHeuristic
object is transformed into an array with a null value at index 0 (because it matches the heuristic defined in Firebase docs) whereas notMatchesHeuristic
is left intact. This is especially "nice" if you have dynamic data like we do - so we don't know untill runtime if it will match heauristic or not.
However this portion of the docs doesn't seem to hold:
You can't currently change or prevent this behavior. Hopefully understanding it will make it easier to see what one can and can't do when storing array-like data.
You can actually workaround this by requesting items searched by key, so
orderBy="$.key"&startAt="0"
which actually filters-out all items with negative key):{"1":{"id":"foo","value":"bar"},"2":{"id":"w","value":"tf"}}
NB: interestingly, seems Firebase support guys don't know about thi workaround (at least they didn't suggest it when we asked them about this behavior).