如何使用AngularFire2对Firebase中以$key为键的日期列表排序
解决Firebase列表按日期字符串排序的问题
看起来你遇到的问题是Firebase Realtime Database里的数据结构是随机key对应日期字符串,没法直接用orderByChild来排序——因为orderByChild是针对节点的子属性,而你的每个节点只有$key和$value(日期字符串)这两个内置字段对吧?
下面给你两种可行的解决方案,优先推荐第一种客户端排序的方式(如果你的数据量不大的话):
方案一:客户端RxJS排序(推荐)
因为你用的是AngularFire的FirebaseListObservable(或者新版本的Observable<Array<any>>),可以借助RxJS的map操作符,在数据返回客户端后进行排序。核心思路是把每个条目的$value(日期字符串)转换成Date对象,然后比较时间戳来排序。
修改你的getBlackList方法如下:
import { map } from 'rxjs/operators'; getBlackList(): Observable<any[]> { return this.db.list(this.datePath).pipe( map(items => items.sort((itemA, itemB) => { // 将日期字符串转为Date对象,获取时间戳进行比较 const dateA = new Date(itemA.$value); const dateB = new Date(itemB.$value); // 升序排序(旧日期在前),如果要降序就反过来:dateB.getTime() - dateA.getTime() return dateA.getTime() - dateB.getTime(); })) ); }
注意事项:
- 确保你的日期字符串能被
Date构造函数正确解析,你当前的Wed Jan 10 2018 00:00:00 GMT-0500 (EST)格式是标准的,没问题; - 如果数据量很大(比如上千条),客户端排序会有性能损耗,这时候可以考虑方案二。
方案二:调整数据结构(服务器端排序)
如果希望在Firebase服务器端完成排序,可以调整你的数据结构,把日期作为节点的一个子属性,而不是直接作为value。比如把每个条目改成:
{ "wlekcbalwvboqwivba": { "date": "Wed Jan 10 2018 00:00:00 GMT-0500 (EST)" }, "s243545dkjvbaskdvbj": { "date": "Thu Feb 8 2018 00:00:00 GMT-0500 (EST)" } }
这样你就可以用orderByChild('date')来在服务器端排序了:
getBlackList(): Observable<any[]> { return this.db.list(this.datePath, ref => ref.orderByChild('date')); }
额外优化建议:
如果可以的话,建议把日期存储为时间戳数字(比如new Date().getTime()返回的毫秒数),这样排序时不需要解析字符串,性能更好,也能避免日期格式解析的潜在问题。
内容的提问来源于stack exchange,提问作者Mel Pacheco
相关产品推荐
相关产品推荐

