Single integer as key in firebase (Firebase array behavior)

前端 未结 4 1211
粉色の甜心
粉色の甜心 2021-02-10 21:58

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

4条回答
  •  礼貌的吻别
    2021-02-10 22:22

    TL;DR;

    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

    Explanation

    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.

    Workaround (REST API)

    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

    • this https://workaround-arrays-bagohack.firebaseio.com/matchesHeuristic.json?print=pretty is broken
    • this is intact https://workaround-arrays-bagohack.firebaseio.com/matchesHeuristic.json?orderBy=%22$key%22&startAt=%220%22&print=pretty (add a meaningless filter like this one 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).

提交回复
热议问题