orderByChild无法在Firebase中运行

Joh*_*ews 32 javascript firebase firebase-realtime-database

我正在尝试查询我的数据库,以便它根据子键检索有序列表.我这样做(见下文),但没有任何反应,这意味着它返回一个完全按照存储在Firebase数据库中的方式排序的对象.到底是怎么回事?

self.getAllProfiles = function () {
    var qProfile = $q.defer();
    var ref = new Firebase(FBURL);
    ref.child("users").orderByChild('last_update').on("value", function (snapshot) {
        console.log(snapshot.val()) // HERE IS WHERE IT SHOULD BE ORDERED
        qProfile.resolve(snapshot.val());
    }, function (errorObject) {
        qProfile.reject(errorObject);
    });
    return qProfile.promise;
};
Run Code Online (Sandbox Code Playgroud)

要添加,我的用户节点如下所示:

users
   /$username
       /last_update
       /id
       /data
          /profile_image
          /display_name
Run Code Online (Sandbox Code Playgroud)

这是一个快照:

Tester: Object
   github: Object
   last_update: 1447732462170
   userId: "github:12345"
Run Code Online (Sandbox Code Playgroud)

Fra*_*len 83

当您调用时snapshot.val(),您将返回一个JSON对象.JSON对象中的键顺序由浏览器决定,而不是由Firebase决定.

为了让孩子们顺序:

self.getAllProfiles = function () {
    var qProfile = $q.defer();
    var ref = new Firebase(FBURL);
    ref.child("users").orderByChild('last_update').on("value", function (snapshot) {
        snapshot.forEach(function(child) {
            console.log(child.val()) // NOW THE CHILDREN PRINT IN ORDER
        });
        qProfile.resolve(snapshot.val());
    }, function (errorObject) {
        qProfile.reject(errorObject);
    });
    return qProfile.promise;
};
Run Code Online (Sandbox Code Playgroud)

您可以将q.resolve()呼叫保留在原来的位置:snapshot.forEach()不是异步呼叫.

  • 因此,如果我们需要排序数据,我们必须使用新键创建一个新对象,或者将每个child.val()放在一个数组中.这不是非常低效吗? (14认同)
  • 我觉得他们需要在官方文档中添加这个警告,因为事实上我已经正确地写出了查询,没有错误但是仍然按照数据库中的顺序获取数据会让我感到难过,直到我遇到这个答案. (5认同)
  • 你介意回答@Pier的问题吗?我也有同样的问题. (4认同)
  • @Onichan请看我的回答. (2认同)
  • 你的意思是像这里的文档中的例子?https://firebase.google.com/docs/database/web/lists-of-data#listen_for_value_events (2认同)
  • 哇,过去 2 年里,我在项目中的 21 个地方使用了 orderByChild,然后才发现我做错了......(在用户报告错误并进一步挖掘之后)。似乎是时候创建一个像 getOrderedResults(snapshot) { var obj = {} snapshot.forEach(function(child) { obj[child.key] = child.val() }); 这样的包装器 返回对象} (2认同)

use*_*289 15

我知道这个问题已经回答并且已经超过1年了,但由于评论部分仍有一些混淆,我想补充一些信息.

问题

最初的问题是OP想要根据Firebase实时数据库中的子密钥检索有序列表,但是.orderByChild('arg')不能按预期工作.

但是没有按预期工作的不是.orderByChild('arg'),但是.on("value", callback).因为.on("value", callback)与其他eventTypes有点不同.on("child_added", callback).

假设我们有一个firebase实时数据库,如下所示:

{
    myData: {
        -KYNMmYHrzLcL-OVGiTU: {
             NO: 1,
             image: ...
        },
        -KYNMwNIz4ObdKJ7AGAL: {
             NO: 2,
             image: ...
        },
        -KYNNEDkLpuwqQHSEGhw: {
             NO: 3,
             image: ...
        },
    }
}
Run Code Online (Sandbox Code Playgroud)

-

如果我们使用.on("value", callback),callback()将被调用1次,并返回3个对象的Object Array.

ref.on("value", function(snapshot) {
    console.log(snapshot.val());
    // Please see Frank van Puffelen's answer
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

-

如果我们使用.on("child_added", callback),callback()将被调用3次,每次返回一个Object,并按顺序返回它们.

ref.once("child_added", function(snapshot) { 
    console.log(snapshot.val());
    // The objects are returned in order, do whatever you like
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

结论

如果您只需要从firebase获取有序数据(例如初始化UI).那么ref.orderByChild('arg').once("child_added", callback)适合您,它简单易用.

但是,如果由于某种原因需要使用ref.orderByChild('arg').on("value", callback),请参阅Frank van Puffelen的回答.

参考

请阅读Firebase文档,了解有关on(eventType, callback, cancelCallbackOrContext, context)其参数及其返回值的更多信息.

另一个有用的文档:使用Web上的数据列表

  • 你看到不同的真正原因是FIB查询结果的类型是'字典',其中记录的'key'(id)是字典的'key'.因此,JS(浏览器)按其键对该列表进行排序.这就是为什么如果你查询'child_added'(逐个)或使用'snapshot.forEach',你将解决这个现象.所以这更像是JS的东西,而不是FIB的东西.因为这个原因,@ frank-van-puffelen的答案更正确. (3认同)

Ren*_*lho 5

使用value事件监听器订购:

firebase.database().ref('/invoices').orderByChild('name').on('value', snapshot => {
    snapshot.forEach(child => {
        console.log(child.key, child.val());
    });
}
Run Code Online (Sandbox Code Playgroud)

如果您想颠倒顺序,请尝试:

function reverseSnapshotOrder (snapshot) {
  let reversed = [];

  snapshot.forEach(child => {
    reversed.unshift(child);
  });

  return reversed;
}

reverseSnapshotOrder(snapshot).forEach(child => {
  console.log(child.key, child.val());
});
Run Code Online (Sandbox Code Playgroud)

请参阅:https : //firebase.google.com/docs/database/web/lists-of-data#listen_for_value_events