我有三个带有键的对象,如下所示:
它们的格式为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
这里有什么我想念的吗?
答案 0 :(得分:10)
TL; DR:确保您的搜索条件中始终包含非数字字符,例如: ref.orderByKey().startAt("20160901-").endAt("20160931~")
。
在Firebase中,所有键都存储为字符串。但是我们使开发人员可以在数据库中存储数组。为了允许我们将数组索引存储为字符串属性。所以ref.set(["First", "Second", "Third"])
实际上存储为:
"0": "First"
"1": "Second"
"2": "Third"
当您从Firebase获取数据时,它会再次将其转换为数组。但是对于当前的用例来说,理解它是作为键值对存储在字符串键中非常重要。
执行查询时,Firebase会尝试检测您是否正在查询数值范围。当它认为这是你的意图时,它会将参数转换为数字,并根据服务器上密钥的数字转换进行查询。
在您的情况下,因为您只查询数值,它将切换到此数字查询模式。但由于你的密钥实际上都是字符串,所以没有任何东西可以匹配。
出于这个原因,我建议你用常量字符串作为前缀。任何有效的角色都可以,我在测试中使用了-
。这会欺骗我们的“它是一个阵列吗?”检查,一切都会以你想要的方式运作。
更快的解决方法是确保您的条件不可转换为数字。在第一个片段中,我通过向startAt()
添加一个非常低范围的ASCII字符和一个非常高的ASCII字符endAt()
来完成此操作。
这两种方法都是Firebase处理数组的方法。不幸的是,API没有一种简单的方法来处理它,并且需要这样的解决方法。