4

如果我将数据插入到node/a/0Firebase 中。

结果将a被视为一个数组a[0]

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

      "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

4 回答 4

8

Firebase 没有对数组的原生支持。如果你存储一个数组,它实际上会被存储为一个以整数作为键名的“对象”。

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

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

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

于 2013-07-21T21:48:19.743 回答
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]

希望这对某人有帮助!

于 2017-02-02T10:04:16.600 回答
1

是的,将 0 和 1 作为键存储会有问题,因为 Firebase 会认为它是一个数组。

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

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

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

于 2017-08-28T09:06:05.463 回答
1

TL;博士;

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

解释

这是 Firebase 的一种已知且不幸的 (IMHO) 行为,在其支持知识库中有深入记录。引用最佳实践:Firebase 中的数组

Firebase 没有对数组的原生支持。如果你存储一个数组,它实际上会被存储为一个以整数作为键名的“对象”。

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

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

特别是,*如果所有键都是整数,并且对象中 0 到最大键之间的键中有一半以上具有非空值,则 Firebase 会将其呈现为数组。后一部分很重要,请牢记。

您目前无法更改或阻止此行为。希望理解它可以更容易地了解在存储类似数组的数据时可以做什么和不能做什么。

因此,我为您设置了一个小型复制器。原始数据

{
  "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保持不变。如果您像我们一样拥有动态数据,这尤其“好” - 所以我们直到运行时才知道它是否会匹配启发式。

解决方法(REST API)

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

您目前无法更改或阻止此行为。希望理解它可以更容易地了解在存储类似数组的数据时可以做什么和不能做什么。

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

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

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

于 2018-01-18T12:50:13.307 回答