orderByChild无法在Firebase中运行

时间:2015-11-24 12:34:31

标签: 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;
};

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

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

这是一张快照:

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

4 个答案:

答案 0 :(得分:76)

当您调用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;
};

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

答案 1 :(得分:15)

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

问题

最初的问题是OP想要根据Firebase实时数据库中的子密钥检索有序列表,但* Hostname was NOT found in DNS cache * Trying 204.9.224.11... * Connected to familysearch.org (204.9.224.11) port 443 (#0) * successfully set certificate verify locations: * CAfile: none CApath: /etc/ssl/certs * SSL connection using AES128-SHA * Server certificate: * subject: C=US; ST=Utah; L=Salt Lake City; O=Intellectual Reserve Inc.; OU=Intellectual+Reserve+Inc.; CN=*.familysearch.org * start date: 2015-06-01 00:00:00 GMT * expire date: 2017-06-05 12:00:00 GMT * subjectAltName: familysearch.org matched * issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=DigiCert SHA2 High Assurance Server CA * SSL certificate verify ok. > GET /platform/tree/persons/LVDH-ZZT/families.json HTTP/1.1 Host: familysearch.org Accept: */* Authorization: BearerUSYS79A3702777***************************** < HTTP/1.1 401 Unauthorized < Cache-Control: no-cache, no-store, no-transform, must-revalidate, max-age=0 < Content-Location: /tree/persons/LVDH-ZZT/families < Content-Type: application/json < Date: Thu, 08 Dec 2016 12:53:04 GMT < Link: <https://ident.familysearch.org/cis-web/oauth2/v3/authorization>; rel="http://oauth.net/core/2.0/endpoint/authorize" < Link: <https://ident.familysearch.org/cis-web/oauth2/v3/token>; rel="http://oauth.net/core/2.0/endpoint/token" * Server Apache-Coyote/1.1 is not blacklisted < Server: Apache-Coyote/1.1 < Vary: Accept, Accept-Language, Accept-Encoding, Expect < Vary: Accept-Encoding < Warning: 400 FamilySearch "Unable to read tf person." < Warning: 199 FamilySearch Best Practice Violation: Should specify versioned media type in Accept header, e.g. one of [ "application/x-gedcomx-v1+xml", "application/x-gedcomx-v1+json", "application/atom+xml", "application/x-gedcomx-atom+json", "application/x-fs-v1+xml", "application/x-fs-v1+json" ]. < X-PROCESSING-TIME: 5 < transfer-encoding: chunked < Connection: Close < * Closing connection 0 { "errors" : [ { "code" : 401, "message" : "Unable to read tf person.", "stacktrace" : "GET http://tf.prod.us-east-1.prod.fslocal.org/tf/person/LVDH-ZZT?oneHops=cards returned a response status of 401 Unauthorized:\n{\n\"401\": \"Unauthorized\"\n}" } ] } 无法按预期工作。

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

实施例

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

.on("child_added", callback)

-

如果我们使用{ myData: { -KYNMmYHrzLcL-OVGiTU: { NO: 1, image: ... }, -KYNMwNIz4ObdKJ7AGAL: { NO: 2, image: ... }, -KYNNEDkLpuwqQHSEGhw: { NO: 3, image: ... }, } } ,则回调()将被调用一次,并返回一个包含3个对象的对象数组。

.on("value", callback)

enter image description here

-

如果我们使用ref.on("value", function(snapshot) { console.log(snapshot.val()); // Please see Frank van Puffelen's answer } ,则回调()将被调用3次,每次返回一个对象,并按顺序返回

.on("child_added", callback)

enter image description here

结论

如果您只需要从firebase获取有序数据(例如初始化UI)。那么ref.once("child_added", function(snapshot) { console.log(snapshot.val()); // The objects are returned in order, do whatever you like } 非常适合您,它简单易用。

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

参考

请阅读Firebase Document,了解有关ref.orderByChild('arg').on("value", callback),其参数及其返回值的详情。

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

答案 2 :(得分:2)

使用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

答案 3 :(得分:0)

我在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;      
     } 
}];