Firebase OrderByKey与startAt和endAt给出错误的结果 [英] Firebase OrderByKey with startAt and endAt giving wrong results

查看:119
本文介绍了Firebase OrderByKey与startAt和endAt给出错误的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有3个对象,它们看起来像这样:



格式为YYYYMMDD。我正在尝试获取一个月的数据。但是我没有得到所需的输出。

当我这样查询时:

  var ref = db.child( -  KPXECP6a1pXaM4gEYe0); 
$ b $ 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 ()函数(childSnapshot){
console.log(childSnapshot.key);
});
});
snapshot.forEach

我得到这个:

  objects:0 






如果我在结尾使用〜符号,

  ref.orderByKey()。startAt(20160901)。endAt(20160932 ())。一次(值,功能(快照){
console.log(objects:+ snapshot.numChildren());
snapshot.forEach(function(childSnapshot){
console.log(childSnapshot.key);
});
});

我得到了输出:

<$ p $对象:3
20160822-KPl446bbdlaiQx6BOPL
20160901-KPl48ID2FuT3tAVf4DW
20160902-KPl4Fr4O28VpsIkB70Z

有什么我在这里失踪?

解决方案

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



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() / code>。



这些都是Firebase处理数组的方式。不幸的是,API没有一个简单的方法来处理它,并需要这样的解决方法。


I have 3 objects with the keys as it looks like this:

They are in format of YYYYMMDD. I am trying to get data of a month. But I am not getting the desired output.

When I query it like this:

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);
    });
});

I get the following output:

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


When I query this along with endAt:

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

I get this:

objects: 0


If I use ~ sign at the end,

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

I get the output:

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

Is there anything I am missing here?

解决方案

Wow... this took some time to dig up. Thanks for the jsfiddle, that helped a lot.

TL;DR: ensure that you always have a non-numeric character in your search criteria, e.g. ref.orderByKey().startAt("20160901-").endAt("20160931~").

Longer explanation

In Firebase all keys are stored as strings. But we make it possible for developers to store arrays in the database. In order to allow that we store the array indices as string properties. So ref.set(["First", "Second", "Third"]) is actually stored as:

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

When you get the data back from Firebase, it'll convert this into an array again. But it is important for your current use-case to understand that it is stored as key-value pairs with string keys.

When you execute a query, Firebase tries to detect whether you're querying a numeric range. When it thinks that is your intent, it converts the arguments into numbers and queries against the numeric conversion of the keys on the server.

In your case since you are querying on only a numeric value, it will switch to this numeric query mode. But since your keys are actually all strings, nothing will match.

For this reason I'd recommend that you prefix keys with a constant string. Any valid character will do, I used a - in my tests. This will fool our "is it an array?" check and everything will work the way you want it.

The quicker fix is to ensure that your conditions are non-convertible to a number. In the first snippet I did this by adding a very low range ASCII character to the startAt() and a very high ASCII character to endAt().

Both of these are workarounds for the way Firebase deals with arrays. Unfortunately the API doesn't have a simple way to handle it and requires such a workaround.

这篇关于Firebase OrderByKey与startAt和endAt给出错误的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆