截至目前,我的数据库结构如下 - 这对我有用。但这是我遇到的不幸事件 - 这两个由自动ID分隔的节点实际上是同一个帖子。
如果您看到上一个是我的数据库结构(使用数组),您将看到每个帖子可能有多个图像,日期和计划。哪个效果很好,但在尝试访问索引等时给了我噩梦。所以我转而采用这种更明智的方式。但现在我有问题将这些帖子分组在一起。例如,下面这两个应该完全相同。
当我从我的数据库中读取数据时,我怎样才能确保 - 我将每个自动ID节点与相应的帖子一起分组?即:这两个节点实际上是相同的帖子 - 如你可以告诉他们每个人都有相同的头衔。
Planit
-LETR-XJvQsZCOpG-T1N
Uid: "ZjtJdkjzuxc0mZn4u9TfWsXa9jh2"
date: "Jun 9, 2018 at 10:00 AM"
image: "https://img.evbuc.com/https%3A%2F%2Fcdn.evbuc.c..
plan: "Bike Rodeo, Safety Presentation and Riding Tour o"
title: "This weekend Plans?"
-LETR-XKqXf7NY1gh6Jm
Uid: "ZjtJdkjzuxc0mZn4u9TfWsXa9jh2"
date: "Jun 11, 2018 at 10:00 AM"
image: "https://img.evbuc.com/https%3A%2F%2Fcdn.evbuc.c..
plan: "Fun night out at the Parlor"
title: "This Weekend Plans?""
我的数据库以前是以这种方式构建的 - 在功能级别上工作得很好,但Firebase程序化主体却错了。我只是把它放进去,所以你可以告诉我实际需要的结构,这些帖子需要以某种方式分组,这样当我从FB读取并将它们加载到表视图中时,相应的数据被存储在一起 - < em>例如 - 1个帖子可以有2个图像,2个计划和2个日期,但只有1个标题(帖子)。
Plant:
-LETYTJh1WEHGgGcVCEp
dates
0: " "
1: " "
images
0: " "
1: " "
plans
0: " "
1: " "
senderId
0: " "
title: close
下面是我用来将数据推送到Firebase的函数 - 我循环遍历一个数组,这样每次迭代都会将图像,日期,计划,标题推送到一个&#34;束&#34;。
for planits in chosenPlanArray {
DataService.instance.uploadPlanitData(withTitleOfPlan: [planits.nameOfEvent!],
withDate: [planits.eventStartsAt!],
withImage: [planits.imageForPlan!],
withTitle: nameOfPlanit.text!,
forUID: (Auth.auth().currentUser?.uid)!,
sendComplete: { (isGood) in
if isGood {
}
})
}
这是我在数据服务类
中的实际实现func uploadPlanitData(withTitleOfPlan plan: [String], withDate: [String], withImage: [String], withTitle: String, forUID uid: String, sendComplete: @escaping (_ status: Bool) -> ()) {
_REF_PLANITS.childByAutoId().updateChildValues(["plan" : plan, "date" : withDate, "image": withImage, "title": withTitle, "Uid": uid])
sendComplete(true)
}
答案 0 :(得分:1)
我想我理解这个问题,有几种方法可以解决。
1)帖子内的小组
PlanIt
plans
-LETR-XJvQsZCOpG-T1N
Uid: "ZjtJdkjzuxc0mZn4u9TfWsXa9jh2"
date: "20180609"
images:
image_0: "https://img.evbuc.com/https%3A%2F%2Fcdn.evbuc.c.."
image_1: "https://img.evbuc.com/https%3A%2F%2Fcdn.evbuc.c.."
plans
plan_0: "Bike Rodeo, Safety Presentation and Riding Tour o"
plan_1: "Bike Rodeo, Safety Presentation and Riding Tour o"
title: "This weekend Plans?"
-Yjijiioimoifijjiuee
Uid: "asdaasdas"
etc
image_0,image_0,plan_0,plan_1等的键将使用childByAutoId创建。
有了这个,你可以加载一次帖子,然后用它获得所有需要的子数据。
请注意,虽然此结构显示为“深层”,但在Firebase NoSQL中通常不鼓励,但您不会对深层数据执行任何查询,并且该数据特定于帖子,所以在这种情况下它很好。
2)对结构进行非规范化/展平
PlanIt
plans
-LETR-XJvQsZCOpG-T1N
Uid: "ZjtJdkjzuxc0mZn4u9TfWsXa9jh2"
date: "20180609"
title: "This weekend Plans?"
-UYijs09as9jiosdijfi
Uid: "some uid"
date: "20180609"
title: "some title"
all_images:
-LETR-XJvQsZCOpG-T1N
image_0: "https://img.evbuc.com/https%3A%2F%2Fcdn.evbuc.c.."
image_1: "https://img.evbuc.com/https%3A%2F%2Fcdn.evbuc.c.."
all_plan_details
-LETR-XJvQsZCOpG-T1N
detail_0: "Bike Rodeo, Safety Presentation and Riding Tour o"
detail_1: "Bike Rodeo, Safety Presentation and Riding Tour o"
第二个选项需要初始加载post节点以获取它的密钥,然后一次调用all_images节点加载图像并调用all_plans来获取它的计划。请注意,我使用posts键来引用all_images和all_plans子节点。
这里的想法是我们使用PlanIt子项的键作为all_images和all_plans节点中该节点的引用。 image_0,image_1,plan_0,plan_1是使用.childByAutoId生成的密钥
第二个选项很酷,因为例如,假设您有一个只包含标题和日期列表的tableview,然后当用户点击它时,您可以将图像或计划加载到另一个视图中...此选项将是一次加载的数据少得多,这使得它更易于管理。
修改强>
为了澄清这个过程,这里是读取计划,图像和计划细节的代码,并根据上述结构将它们打印到控制台。
let mainRef = self.ref.child("PlanIt")
let plansRef = mainRef.child("plans")
let allImagesRef = mainRef.child("all_images")
let allPlanDetailsRef = mainRef.child("all_plan_details")
plansRef.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let childSnap = child as! DataSnapshot
let dict = childSnap.value as! [String: Any]
let planKey = childSnap.key
let title = dict["title"] as! String
let thisPlansImagesRef = allImagesRef.child(planKey)
let thisPlansDetailsRef = allPlanDetailsRef.child(planKey)
thisPlansImagesRef.observeSingleEvent(of: .value, with: { imageSnapshot in
thisPlansDetailsRef.observeSingleEvent(of: .value, with: { planDetailSnapshot in
//printing is done here because firebase is asynchronous and all data
// will be valid for each node ONLY at this point
print("plan: \(planKey) \(title)")
for imageChild in imageSnapshot.children {
let imageChildSnap = imageChild as! DataSnapshot
let image = imageChildSnap.value as! String
print(" image: \(image)")
}
for planDetailChild in planDetailSnapshot.children {
let planDetailChildSnap = planDetailChild as! DataSnapshot
let planDetail = planDetailChildSnap.value as! String
print(" planDetail: \(planDetail)")
}
})
})
}
})
,输出结果为:
plan: plan_0 This weekend plans
image: some image for plan_0
image: another_image for plan_0
planDetail: some plan detail for plan_0
planDetail: another plan detail for plan_0
plan: plan_1 Next weekend plans
我在Firebase中添加了一些文本值,以便更清楚输出中的内容。