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