Firebase 有时只提供我保存的部分值,有时提供所有值
Firebase gives sometimes only parts of my saved values and sometimes everything
我正在尝试编写自己的 Messenger。我将消息保存在 Firebase 数据库中。我正在尝试以正常方式访问消息,我每次都是这样做的(database.database().reference().child("users").....,但它只返回一个很少的消息,有时只有每条消息
我已经用 .childAdded 试过了,但它也不起作用
func fetchMessages() {
self.messages.removeAll()
let uid = Auth.auth().currentUser!.uid
let ref = Database.database().reference().child("users").child(uid).child("chats").child(self.chatuid).child("messages")
ref.observeSingleEvent(of: .value) { (snap) in
guard let data = snap.value as? [String: AnyObject] else { return }
//MARK: data = (messageID, AnyObject)
for (messageID, _) in data {
ref.child(messageID).observeSingleEvent(of: .value) { (snap2) in
guard let data2 = snap2.value as? [String: AnyObject] else { return }
//MARK: data2 = ("message": String, "sentuid": String)
guard let message = data2["message"] as? String else { return }
guard let sentuid = data2["sentuid"] as? String else { return }
let messageToAppend = Message(sentuid: sentuid, message: message)
self.messages.append(messageToAppend)
self.messageTableView.reloadData()
}
}
}
}
//self.messages = Place where I save my fetched messages
Firebase 结构:
{
"users" : {
"V3bLZu61KYTCG0uCWV8LH1f4rRJ3" : {
"chats" : {
"x3GzxwmyLbXrQNNyBF2a82KqrHa2" : {
"messages" : {
"20191014165454" : {
"message" : "Heyho",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165647" : {
"message" : "Blabla",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165754" : {
"message" : "Blabla",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165800" : {
"message" : "Fuchsloch",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165805" : {
"message" : "Jlksaö",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165808" : {
"message" : "Jadfsk",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165811" : {
"message" : "Jskldflsö",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014170041" : {
"message" : "JALSF",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"test" : {
"messange" : "test",
"sentUid" : "MatesForSports"
}
}
}
},
"username" : "Acc2"
},
"x3GzxwmyLbXrQNNyBF2a82KqrHa2" : {
"chats" : {
"V3bLZu61KYTCG0uCWV8LH1f4rRJ3" : {
"messages" : {
"20191014165454" : {
"message" : "Heyho",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165647" : {
"message" : "Blabla",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165754" : {
"message" : "Blabla",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165800" : {
"message" : "Fuchsloch",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165805" : {
"message" : "Jlksaö",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165808" : {
"message" : "Jadfsk",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165811" : {
"message" : "Jskldflsö",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014170041" : {
"message" : "JALSF",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"test" : {
"messange" : "test",
"sentUid" : "MatesForSports"
}
}
}
},
"username" : "Acc1"
}
}
}
我预计该代码会返回大约 10 条消息,但它有时会返回 5 条、有时 3 条甚至仅 2 条消息
我的消息的 firebase 结构是 .child("messages"),然后是唯一 ID,然后是实际消息和一层的发件人
这是一个答案和一个建议。
让我们从使用一些硬编码值复制您的结构开始
users
uid_0
chats
chat_uid_0
messages
unique_id_0
msg: "My Message"
sent_uid: "uid_1"
unique_id_1
msg: "Hello, World"
sent_uid: "uid_3"
unique_id_2
msg: "another message"
sent_uid: "uid_2"
然后是读取消息的代码,遍历它们并打印出消息和 sent_uid
func readMessages() {
let usersRef = self.ref.child("users")
let messagesRef = usersRef.child("uid_0").child("chats").child("chat_uid_0").child("messages")
messagesRef.observeSingleEvent(of: .value, with: { snapshot in
let allMessages = snapshot.children.allObjects as! [DataSnapshot]
for msg in allMessages {
let msgText = msg.childSnapshot(forPath: "msg").value as? String ?? "No Msg"
let sentUid = msg.childSnapshot(forPath: "sent_uid").value as? String ?? "No sender"
print(msgText, sentUid)
}
})
}
输出为
My message uid_1
Hello, World uid_3
another message uid_2
话虽这么说 - 你的结构太深了,应该去规范化。虽然它可能会起作用,但一旦您想查询项目或查找特定用户发布的消息,它就不起作用了。
我不知道您的完整用例,但这会是一个更好的结构
users
uid_0
name: "Hank"
uid_1
name: "Leroy"
chats
uid_0
chat_id_0: true
chat_id_1: true
uid_1
chat_id_5: true
chat_id_0
unique_id_0
msg: "My Message"
sent_uid: "uid_1"
unique_id_1
msg: "Hello, World"
sent_uid: "uid_3"
unique_id_2
msg: "another message"
sent_uid: "uid_2"
使用这种结构,一切都非常浅,很容易获取数据 - 执行查询等。您可以快速检索 uid_0 涉及的所有聊天,获取 uid_3 曾经的任何消息在 uid_1 的聊天中发布或添加观察员,以便在添加聊天时通知其他人。同样,这只是一个示例,可能不适合您的情况,但值得考虑。
我正在尝试编写自己的 Messenger。我将消息保存在 Firebase 数据库中。我正在尝试以正常方式访问消息,我每次都是这样做的(database.database().reference().child("users").....,但它只返回一个很少的消息,有时只有每条消息
我已经用 .childAdded 试过了,但它也不起作用
func fetchMessages() {
self.messages.removeAll()
let uid = Auth.auth().currentUser!.uid
let ref = Database.database().reference().child("users").child(uid).child("chats").child(self.chatuid).child("messages")
ref.observeSingleEvent(of: .value) { (snap) in
guard let data = snap.value as? [String: AnyObject] else { return }
//MARK: data = (messageID, AnyObject)
for (messageID, _) in data {
ref.child(messageID).observeSingleEvent(of: .value) { (snap2) in
guard let data2 = snap2.value as? [String: AnyObject] else { return }
//MARK: data2 = ("message": String, "sentuid": String)
guard let message = data2["message"] as? String else { return }
guard let sentuid = data2["sentuid"] as? String else { return }
let messageToAppend = Message(sentuid: sentuid, message: message)
self.messages.append(messageToAppend)
self.messageTableView.reloadData()
}
}
}
}
//self.messages = Place where I save my fetched messages
Firebase 结构:
{
"users" : {
"V3bLZu61KYTCG0uCWV8LH1f4rRJ3" : {
"chats" : {
"x3GzxwmyLbXrQNNyBF2a82KqrHa2" : {
"messages" : {
"20191014165454" : {
"message" : "Heyho",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165647" : {
"message" : "Blabla",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165754" : {
"message" : "Blabla",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165800" : {
"message" : "Fuchsloch",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165805" : {
"message" : "Jlksaö",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165808" : {
"message" : "Jadfsk",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165811" : {
"message" : "Jskldflsö",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014170041" : {
"message" : "JALSF",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"test" : {
"messange" : "test",
"sentUid" : "MatesForSports"
}
}
}
},
"username" : "Acc2"
},
"x3GzxwmyLbXrQNNyBF2a82KqrHa2" : {
"chats" : {
"V3bLZu61KYTCG0uCWV8LH1f4rRJ3" : {
"messages" : {
"20191014165454" : {
"message" : "Heyho",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165647" : {
"message" : "Blabla",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165754" : {
"message" : "Blabla",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165800" : {
"message" : "Fuchsloch",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165805" : {
"message" : "Jlksaö",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165808" : {
"message" : "Jadfsk",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014165811" : {
"message" : "Jskldflsö",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"20191014170041" : {
"message" : "JALSF",
"sentuid" : "V3bLZu61KYTCG0uCWV8LH1f4rRJ3"
},
"test" : {
"messange" : "test",
"sentUid" : "MatesForSports"
}
}
}
},
"username" : "Acc1"
}
}
}
我预计该代码会返回大约 10 条消息,但它有时会返回 5 条、有时 3 条甚至仅 2 条消息
我的消息的 firebase 结构是 .child("messages"),然后是唯一 ID,然后是实际消息和一层的发件人
这是一个答案和一个建议。
让我们从使用一些硬编码值复制您的结构开始
users
uid_0
chats
chat_uid_0
messages
unique_id_0
msg: "My Message"
sent_uid: "uid_1"
unique_id_1
msg: "Hello, World"
sent_uid: "uid_3"
unique_id_2
msg: "another message"
sent_uid: "uid_2"
然后是读取消息的代码,遍历它们并打印出消息和 sent_uid
func readMessages() {
let usersRef = self.ref.child("users")
let messagesRef = usersRef.child("uid_0").child("chats").child("chat_uid_0").child("messages")
messagesRef.observeSingleEvent(of: .value, with: { snapshot in
let allMessages = snapshot.children.allObjects as! [DataSnapshot]
for msg in allMessages {
let msgText = msg.childSnapshot(forPath: "msg").value as? String ?? "No Msg"
let sentUid = msg.childSnapshot(forPath: "sent_uid").value as? String ?? "No sender"
print(msgText, sentUid)
}
})
}
输出为
My message uid_1
Hello, World uid_3
another message uid_2
话虽这么说 - 你的结构太深了,应该去规范化。虽然它可能会起作用,但一旦您想查询项目或查找特定用户发布的消息,它就不起作用了。
我不知道您的完整用例,但这会是一个更好的结构
users
uid_0
name: "Hank"
uid_1
name: "Leroy"
chats
uid_0
chat_id_0: true
chat_id_1: true
uid_1
chat_id_5: true
chat_id_0
unique_id_0
msg: "My Message"
sent_uid: "uid_1"
unique_id_1
msg: "Hello, World"
sent_uid: "uid_3"
unique_id_2
msg: "another message"
sent_uid: "uid_2"
使用这种结构,一切都非常浅,很容易获取数据 - 执行查询等。您可以快速检索 uid_0 涉及的所有聊天,获取 uid_3 曾经的任何消息在 uid_1 的聊天中发布或添加观察员,以便在添加聊天时通知其他人。同样,这只是一个示例,可能不适合您的情况,但值得考虑。