2015-11-24 76 views
15

我想查詢我的數據庫,以便它檢索基於子鍵的有序列表。我按照如下所示執行(見下文),但沒有任何反應,這意味着它會按照存儲在Firebase數據庫中的相同方式返回對象。到底是怎麼回事?orderByChild不工作在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" 
+0

你可以顯示你的數據無序,然後它看起來像什麼時它作爲快照? –

+0

用快照更新了問題 – JohnAndrews

+1

很難說出你提供的數據是怎麼回事。你能創建一個JSBin來演示你的問題嗎?這可以讓您更容易排查發生的事情。 –

回答

54

當你調用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()不是一個異步調用。

+13

所以如果我們需要排序的數據,我們必須用新的鍵創建一個新的對象或將每個child.val()放入一個數組中。這不是非常低效嗎? – Pier

+4

你介意回答@Pier的問題嗎?我也有同樣的問題。 – Onichan

+1

@Pier你不需要如果你使用其他eventTypes,請參閱我的答案的細節。 – user2875289

11

我知道這個問題已經回答,並且已經超過1年了,但由於評論部分仍然存在一些混淆,我想補充一些信息。

問題

原來的問題是,OP要檢索基於從火力地堡實時數據庫中的子鍵的有序列表,但.orderByChild('arg')不能按預期工作。

但沒有按預期工作的不是.orderByChild('arg'),而是.on("value", callback)。因爲.on("value", callback)與其他eventTypes有點不同,例如.on("child_added", callback)

假設我們有如下一個火力點實時數據庫:

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

-

如果我們使用.on("value", callback),回調()將被稱爲1次,並返回對象3個對象的數組。

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

enter image description here

-

如果我們使用.on("child_added", callback),回調()將被調用3次,每次返回一個對象,他們是爲了返回

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

enter image description here

結論

如果你只需要從火力獲取有序的數據(例如初始化UI)。然後ref.orderByChild('arg').once("child_added", callback)適合你很好,這是簡單,易於使用。

但是,如果由於某種原因您需要使用ref.orderByChild('arg').on("value", callback),那麼請參閱Frank van Puffelen的回答。

參考

請閱讀Firebase Document更多有關on(eventType, callback, cancelCallbackOrContext, context),他們的觀點和他們的返回值。

另一個有用的文檔:Work with Lists of Data on the Web

+1

您看到不同的真正原因是FIB查詢結果的類型是'dictionary',其中'key'(id )的記錄是字典的「關鍵」。因此,JS(瀏覽器)通過它的關鍵字對這個列表進行排序。 這就是爲什麼如果你查詢'child_added'(一個接一個)或使用'snapshot.forEach'你會解決這個現象。 所以這更多的是JS的東西,而不是FIB的東西。 @ frank-van-puffelen的回答更正確。 –

+0

@EliLivshitz完全同意。 – user2875289

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;  
    } 
}]; 
相關問題