orderByChild 在 Firebase 中不起作用

orderByChild not working in Firebase

我正在尝试查询我的数据库,以便它检索基于子键的有序列表。我按如下方式执行(见下文),但没有任何反应,这意味着它 returns 一个对象的排序方式与它存储在 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;
};

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

users
   /$username
       /last_update
       /id
       /data
          /profile_image
          /display_name

这是一张快照:

Tester: Object
   github: Object
   last_update: 1447732462170
   userId: "github:12345"

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

要按顺序获取 children 使用快照的 built-in forEach 方法:

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

您可以将 q.resolve() 调用留在原处:snapshot.forEach() 不是异步调用。

我知道这个问题已经回答了 1 年多了,但由于评论部分仍然存在一些混淆,我想补充一些信息。

问题

最初的问题是 OP 想要从 Firebase 实时数据库中检索基于子键的有序列表,但是 .orderByChild('arg') 没有按预期工作。

但没有达到预期效果的不是.orderByChild('arg'),而是.on("value", callback)。因为 .on("value", callback).on("child_added", callback).

等其他事件类型有点不同

例子

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

{
    myData: {
        -KYNMmYHrzLcL-OVGiTU: {
             NO: 1,
             image: ...
        },
        -KYNMwNIz4ObdKJ7AGAL: {
             NO: 2,
             image: ...
        },
        -KYNNEDkLpuwqQHSEGhw: {
             NO: 3,
             image: ...
        },
    }
}

--

如果我们使用 .on("value", callback),callback() 将被调用 1 次,并且 return 一个包含 3 个对象的对象数组。

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

--

如果我们使用 .on("child_added", callback),callback() 将被调用 3 次,每次 returns 一个对象,它们被 returned in订单.

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

结论

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

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

参考

请阅读 Firebase Document 以获取有关 on(eventType, callback, cancelCallbackOrContext, context)、它们的参数和它们的 return 值的更多信息。

另一个有用的文档:Work with Lists of Data on the Web

我在 iOS 遇到过同样的问题。如果将快照转换为 NSDictionary 对象,它会转换为无序列表。 Objective-c 版本以备不时之需:

[[self.refChild queryOrderedByChild:@"date_created"] 
  observeEventType:FIRDataEventTypeValue 
         withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {

     for (FIRDataSnapshot *child in snapshot.children) {  

          NSDictionary *anObject = child.value; 
          NSString *aKey         = child.key;      
     } 
}];

使用 value 事件侦听器进行排序:

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

如果你想颠倒顺序,试试:

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

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

  return reversed;
}

reverseSnapshotOrder(snapshot).forEach(child => {
  console.log(child.key, child.val());
});

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