【问题标题】:Firebase OrderByKey with startAt and endAt giving wrong resultsFirebase OrderByKey 与 startAt 和 endAt 给出错误的结果
【发布时间】:2016-08-22 09:47:39
【问题描述】:

我有 3 个带有键的对象,如下所示:

它们的格式为 YYYYMMDD。我正在尝试获取一个月的数据。但我没有得到想要的输出。

当我这样查询时:

var ref = db.child("-KPXECP6a1pXaM4gEYe0");

ref.orderByKey().startAt("20160901").once("value", function (snapshot) {
    console.log("objects: " + snapshot.numChildren());
    snapshot.forEach(function(childSnapshot) {
        console.log(childSnapshot.key);
    });
});

我得到以下输出:

objects: 3
20160822-KPl446bbdlaiQx6BOPL
20160901-KPl48ID2FuT3tAVf4DW
20160902-KPl4Fr4O28VpsIkB70Z

当我与 endAt 一起查询时:

ref.orderByKey().startAt("20160901").endAt("20160932").once("value", function (snapshot) {
    console.log("objects: " + snapshot.numChildren());
    snapshot.forEach(function(childSnapshot) {
        console.log(childSnapshot.key);
    });
});

我明白了:

objects: 0

如果我在末尾使用 ~ 符号,

ref.orderByKey().startAt("20160901").endAt("20160932~").once("value", function (snapshot) {
    console.log("objects: " + snapshot.numChildren());
    snapshot.forEach(function(childSnapshot) {
        console.log(childSnapshot.key);
    });
});

我得到了输出:

objects: 3
20160822-KPl446bbdlaiQx6BOPL
20160901-KPl48ID2FuT3tAVf4DW
20160902-KPl4Fr4O28VpsIkB70Z

这里有什么我遗漏的吗?

【问题讨论】:

  • 您在问题中包含了 JSON 树的图片。请将其替换为实际的 JSON 作为文本,您可以通过单击 Firebase 数据库控制台中的导出按钮轻松获取该文本。将 JSON 作为文本使其可搜索,使我们可以轻松地使用它来测试您的实际数据并在我们的答案中使用它,通常只是一件好事。重现问题的 jsfiddle/jsbin 会更好。
  • @FrankvanPuffelen 给我一些时间。我正在制作小提琴
  • @FrankvanPuffelen,这里是小提琴:jsfiddle.net/kirtan403/g0o6y7wv

标签: javascript firebase firebase-realtime-database


【解决方案1】:

哇...这需要一些时间来挖掘。感谢 jsfiddle,帮助很大。

TL;DR:确保您的搜索条件中始终包含非数字字符,例如ref.orderByKey().startAt("20160901-").endAt("20160931~").

更长的解释

在 Firebase 中,所有键都存储为字符串。但是我们使开发人员可以在数据库中存储数组。为了允许我们将数组索引存储为字符串属性。所以ref.set(["First", "Second", "Third"])实际上存储为:

"0": "First"
"1": "Second"
"2": "Third"

当您从 Firebase 取回数据时,它会再次将其转换为数组。但是对于您当前的用例来说,重要的是要了解它是作为键值对与字符串键一起存储的。

当您执行查询时,Firebase 会尝试检测您是否在查询数字范围。当它认为这是您的意图时,它会将参数转换为数字,并针对服务器上键的数字转换进行查询。

在您的情况下,由于您仅查询数值,因此它将切换到此数字查询模式。但是由于您的键实际上都是字符串,因此没有任何匹配项。

出于这个原因,我建议您使用常量字符串作为键的前缀。任何有效字符都可以,我在测试中使用了-。这会愚弄我们的“它是一个数组吗?”检查一下,一切都会按照你想要的方式进行。

更快的解决方法是确保您的条件不可转换为数字。在第一个 sn-p 中,我通过在 startAt() 中添加一个非常低范围的 ASCII 字符和在 endAt() 中添加一个非常高的 ASCII 字符来做到这一点。

这两种方法都是 Firebase 处理数组的方法。不幸的是,API 没有简单的方法来处理它,需要这样的解决方法。

【讨论】:

  • 哇!如果我不发布,我永远不会得到它。我花了4个多小时才明白发生了什么!我在 Android 和 javascript 中尝试过,最后认为 sdk 有问题。因此,我在文档中未能理解 Children with a key that can be parsed as a 32-bit integer come first, sorted in ascending order 的那条小线就是答案!精彩的解释!每个特殊字符之前都有空格,最后是 ~,这就是为什么它可以正常使用该选项 (asciitable.com) ..
  • 最后一个问题,是否可以在不暴露 api 密钥的情况下为 firebase 创建小提琴?
  • 不。要访问 Firebase 数据库,您需要拥有数据库的 URL 和 API 密钥。但请注意,这不是安全风险:stackoverflow.com/questions/37482366/…
  • 所以,我会在分享之前为那个节点设置安全规则!谢谢! :)
猜你喜欢
  • 2021-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-19
  • 2018-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多