OrderByChild не работает в Firebase
Я пытаюсь запросить мою базу данных так, чтобы она получала упорядоченный список на основе дочернего ключа. Я делаю это следующим образом (см. Ниже), но ничего не происходит, что означает, что он возвращает объект, упорядоченный точно так же, как он хранится в базе данных 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;
};
Чтобы добавить, мои пользователи node выглядят следующим образом:
users
/$username
/last_update
/id
/data
/profile_image
/display_name
Вот снимок:
Tester: Object
github: Object
last_update: 1447732462170
userId: "github:12345"
Ответы
Ответ 1
Когда вы вызываете 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()
не является асинхронным вызовом.
Ответ 2
Я знаю, что на этот вопрос был дан ответ и ему больше 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 раз и возвращает массив объектов из 3 объектов.
ref.on("value", function(snapshot) {
console.log(snapshot.val());
// Please see Frank van Puffelen answer
}
![введите описание изображения здесь]()
-
Если мы используем .on("child_added", callback)
, callback() будет вызываться 3 раза, каждый раз возвращает объект, и они возвращаются в порядке.
ref.once("child_added", function(snapshot) {
console.log(snapshot.val());
// The objects are returned in order, do whatever you like
}
![введите описание изображения здесь]()
Заключение
Если вам нужно только получить упорядоченные данные из firebase (например, для инициализации пользовательского интерфейса.) Тогда ref.orderByChild('arg').once("child_added", callback)
подходит вам хорошо, он прост и прост в использовании.
Однако, если по какой-то причине вам нужно использовать ref.orderByChild('arg').on("value", callback)
, то, пожалуйста, см. ответ Франк ван Пуффлен.
Ссылка
Прочтите Firebase Document для получения дополнительной информации о on(eventType, callback, cancelCallbackOrContext, context)
, их аргументах и их возвращаемых значениях.
Еще один полезный документ: Работа со списками данных в Интернете
Ответ 3
Я боролся с той же проблемой в 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;
}
}];