单个整数作为firebase中的键(Firebase数组行为)

时间:2013-07-21 21:28:49

标签: firebase

如果我将数据插入firebase中的node/a/0

结果会将a视为数组a[0]

同样,如果我在node/a/1中设置数据,第一个数组将变为空

      "a" : [ null, {
        "-J-22j_Mb59l0Ws0H9xc" : {
          "name" : "chok wee ching"
        }
      } ]

但如果node/a/2

,那就没问题了
      "a" : {
        "2" : {
          "-J-25xjEXUqcpsC-5LOE" : {
            "name" : "chok wee ching"
          }
        }
      }

我的猜测,firebase会自动将单个0和1视为一个数组。 我该如何防止这种情况?

4 个答案:

答案 0 :(得分:7)

Firebase没有对数组的本机支持。如果存储数组,它实际上存储为“对象”,整数作为键名。

但是,为了帮助人们在Firebase中存储数组,当您调用.val()或使用REST api从Firebase读取数据时,如果数据看起来像一样,Firebase将会将其渲染为数组。

特别是,如果所有键都是整数,并且对象中超过一半的键与对象中的最大键具有非空值,则Firebase会将其渲染为数组。这是您遇到的启发式的后半部分。您的第二个示例仅为2设置值,而不是0和1,因此不到一半的键具有值,因此Firebase将其呈现为对象。

您目前无法更改或阻止此行为(虽然这是一个常见的混淆源,因此我们可能会在未来对此进行一些调整)。但是,一旦理解了行为,通常很容易处理。如果您需要进一步的帮助,也许您可​​以扩展您的问题来解释您需要完成什么以及此行为如何阻止它。

答案 1 :(得分:1)

我遇到了同样的问题,但实际上想在Swift中使用数字键数组([Int:AnyObject])。我写了这个函数,以确保总是有一个数组(没有空值):

func forceArray(from: Any?) -> [Int:AnyObject] {        
    var returnArray = [Int:AnyObject]()

    if let array = from as? [String:AnyObject] {
        for (key, value) in array {
            if let key = Int(key) {
                returnArray[key] = value
            }
        }
        return returnArray
    }

    if let array = from as? [AnyObject] {
        for (key, value) in array.enumerated() {
            if !(value is NSNull) {
                returnArray[key] = value
            }
        }
        return returnArray
    }

    return returnArray
}

结果:

["0":1, "1":2]变为:[0:1, 1:2]

{"0":1, "6":2}变为:[0:1, 6:2]

["0":1, "1": null, "2":2]变为:[0:1, 2:2]

希望这对某人有帮助!

答案 2 :(得分:1)

是的,将密钥存储为0和1会产生问题,因为Firebase会认为它是一个数组。

我的简单解决方法是使用:

String(format:"%03d", intValue)

这样生成的密钥将是" 000"和" 001",并且可以轻松地将它们转换回Int。

答案 3 :(得分:1)

TL; DR;

REST API的解决方法:添加一个无意义的过滤器,例如orderBy="$.key"&startAt="0",它实际上过滤掉所有带负片的项目):https://workaround-arrays-bagohack.firebaseio.com/matchesHeuristic.json?orderBy=%22 $ key%22& startAt =%220%22& print =漂亮

说明

这是Firebase的已知和不幸(恕我直言)行为,记录在其支持知识库的深处。引自Best Practices: Arrays in Firebase

  

Firebase没有对数组的本机支持。如果你存储一个数组,它   真的存储为“对象”,整数作为键名。

     

// we send this ['hello', 'world']   // Firebase stores this {0:'hello', 1: 'world'}

     

但是,要帮助那些存储阵列的人   在Firebase中,当您调用.val()或使用REST api读取数据时,如果   数据看起来像一个数组,Firebase会将其渲染为数组。

     

特别是,*如果所有键都是整数,则超过一半   0和对象中的最大键之间的键具有非空   值,然后Firebase将其呈现为数组。后一部分是   重要的是要记住。

     

您目前无法更改或阻止此行为。希望   了解它将使人们更容易看到一个人能做什么,不能做什么   存储类似数据时。

所以我为你设置了一个小的repro。 原始数据

{
  "matchesHeuristic": {
      "1": {
          "id": "foo",
          "value": "bar"
      },
      "2": {
          "id": "w",
          "value": "tf"
      }
  },
  "notMatchesHeuristic": {
      "1": {
          "id": "foo",
          "value": "bar"
      },
      "365": {
          "id": "w",
          "value": "tf"
      }
  }
}

由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"
    }
  }
}

正如您所见,matchesHeuristic对象被转换为索引为0的空值的数组(因为它与Firebase文档中定义的启发式匹配),而notMatchesHeuristic保持不变。如果你有像我们这样的动态数据,这尤其“好” - 所以我们不知道如果它与heauristic匹配还是不匹配的运行时。

解决方法(REST API)

然而,这部分文档似乎并不成立:

  

您目前无法更改或阻止此行为。希望   了解它将使人们更容易看到一个人能做什么,不能做什么   存储类似数据时。

您实际上可以通过请求按键搜索的项目来解决此问题,所以

{"1":{"id":"foo","value":"bar"},"2":{"id":"w","value":"tf"}}

NB:有趣的是,似乎Firebase支持人员不了解这种解决方法(至少当我们向他们询问这种行为时他们没有建议)。