孩子的 Firebase 查询排序无法正常工作

Posted

技术标签:

【中文标题】孩子的 Firebase 查询排序无法正常工作【英文标题】:Firebase query ordering by child not working properly 【发布时间】:2017-10-30 22:33:14 【问题描述】:

问题

我正在尝试按 createionDate 查询对象列表。由于某种原因,它不会按升序获取对象。

我的数据结构

我的代码

func fetchQuest() 
        
        guard let uid = selectedUID else return
        
        let ref = FIRDatabase.database().reference().child("questsByUID").child(uid)
        let query = ref.queryOrdered(byChild: "CreationDate")
        query.observeSingleEvent(of: .value, with:  (snapshot) in
            
            
            guard let dictionaries = snapshot.value as? [String: Any] else return
            dictionaries.forEach( (key, value) in
                
                guard let dictionary = value as? [String : Any] else return
                let quest = Quest(uid: uid, dictionary: dictionary)
                quest.questID = key
                print("quest name is: ", quest.questName)
                self.board.append(quest)
                
            )
            self.collectionView?.reloadData()
        )  (err) in
            print("unable to fetch quest:", err)
        
    

我的模型

class Quest 

var questID = ""
let questName: String
let creatorUID: String
let creationDate: Date

init(uid: String, dictionary: [String: Any]) 
    self.questName = dictionary["questName"] as? String ?? ""
    self.creatorUID = uid
    let secondsFrom1970 = dictionary["creationDate"] as? Double ?? 0
    self.creationDate = Date(timeIntervalSince1970: secondsFrom1970)

控制台输出

任务名称:第三个任务

任务名称:第二个任务

任务名称:艾达的第四个任务

任务名称是:艾达的第一个任务

【问题讨论】:

【参考方案1】:

鉴于 Firebase 数据库区分大小写,请尝试将您的查询更改为:

let query = ref.queryOrdered(byChild: "CreationDate")

到:

let query = ref.queryOrdered(byChild: "creationDate")

您的Quest 模型类已经使用了正确的拼写。

更新。正如另一个答案所提到的,字典是 not 保留顺序的。因此,您应该改用 FIRDataSnapshot.children 迭代器。例如:

query.observeSingleEvent(of: .value)  
    (snapshots) in
    for child in snapshots.children 
        let snapshot = child as! DataSnapshot
        guard let dictionary = snapshot.value as? [String : Any] else  return 
        let quest = Quest(uid: uid, dictionary: dictionary)
        quest.questID = snapshot.key
        ...
    

请注意,我仍然使用与原始代码相同的 observeSingleEvent

【讨论】:

输出仍然不是升序。它似乎是随机的 @JeffreyChang 你是对的!发现另一个错误...请检查更新的答案;)【参考方案2】:

我认为顺序不同,因为字典是键值对的无序集合。所以我认为既然你想以有序的方式获取值,你可以使用.childAdded的eventType,因为根据文档:

与返回位置全部内容的 value 不同, childAdded 为每个现有的孩子触发一次,然后再次触发 每次向指定路径添加一个新子节点时

所以你可以像这样修改你的代码:

    首先作为另一个答案将CreationDate更改为creationDate

    第二次使用.childAdded而不是.value作为事件类型。

let query = ref.queryOrdered(byChild: "creationDate") query.observe(.childAdded, with: (snapshot) in...

【讨论】:

切换到 .childAdded 后,firebase 将只获取 1 个对象而不是整个列表。我认为这是因为 .observeSingleEvent 这一行。抱歉回复晚了 @JeffreyChang 您可以使用 observe 代替 observeSingleEvent ,请查看更新后的答案

以上是关于孩子的 Firebase 查询排序无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

Swift Firebase 快照查询缺少孩子

如何从孩子(firebase)查询所有孩子的值[重复]

使用 firebase 按最新消息对聊天列表进行排序

获取 Firebase 用户中最小的孩子

在应用命令之前,操纵存储在Firebase文档字段中的值

firebase 云计划功能无法正常工作