我正在尝试允许由用户创建的文档(报告)由其他用户查看,然后更新更改。文档显示在tableView中,当被选中时,它显示在ViewController中加载的特定报告的适当数据。然而,当我去选择单个报告的ViewController中的更新按钮时,错误返回,找不到文档。
下面是我正在使用的更新函数的当前代码变体。
private let database = Firestore.firestore()
private init() {}
// UPDATE REPORT
public func updateTheData(
reportPost: ReportPost,
thisReport: String,
completion: @escaping (Bool) -> Void
){
let data = [
"id": reportPost.identifier,
"title": reportPost.title,
"timestamp1": reportPost.timestamp1,
"address": reportPost.address,
"customerPO": reportPost.customerPO,
"authNum": reportPost.authNum,
"contactName": reportPost.contactName,
"contactPhone": reportPost.contactPhone,
"modelNum": reportPost.modelNum,
"serialNum": reportPost.serialNum,
"addInfo": reportPost.addInfo,
"equipProblem": reportPost.equipProblem,
"action": reportPost.action,
"followUp": reportPost.followUp,
"techName1": reportPost.techName1,
"techName2": reportPost.techName2,
"techName3": reportPost.techName3,
"techName4": reportPost.techName4,
"timestamp2": reportPost.timestamp2,
"timestamp3": reportPost.timestamp3,
"timestamp4": reportPost.timestamp4,
"milesTraveled1": reportPost.milesTraveled1,
"milesTraveled2": reportPost.milesTraveled2,
"milesTraveled3": reportPost.milesTraveled3,
"milesTraveled4": reportPost.milesTraveled4,
"travelTime1": reportPost.travelTime1,
"travelTime2": reportPost.travelTime2,
"travelTime3": reportPost.travelTime3,
"travelTime4": reportPost.travelTime4,
"siteTime1": reportPost.siteTime1,
"siteTime2": reportPost.siteTime2,
"siteTime3": reportPost.siteTime3,
"siteTime4": reportPost.siteTime4,
"serviceType1": reportPost.serviceType1,
"serviceType2": reportPost.serviceType2,
"serviceType3": reportPost.serviceType3,
"serviceType4": reportPost.serviceType4,
"timeTotal1": reportPost.timeTotal1,
"timeTotal2": reportPost.timeTotal2,
"timeTotal3": reportPost.timeTotal3,
"timeTotal4": reportPost.timeTotal4,
"partNum1": reportPost.partNum1,
"partNum2": reportPost.partNum2,
"partNum3": reportPost.partNum3,
"partNum4": reportPost.partNum4,
"quantity1": reportPost.quantity1,
"quantity2": reportPost.quantity2,
"quantity3": reportPost.quantity3,
"quantity4": reportPost.quantity4,
"price1": reportPost.price1,
"price2": reportPost.price2,
"price3": reportPost.price3,
"price4": reportPost.price4,
"priceTotal1": reportPost.priceTotal1,
"priceTotal2": reportPost.priceTotal2,
"priceTotal3": reportPost.priceTotal3,
"priceTotal4": reportPost.priceTotal4,
]
let docRef = database.collection("reports").document(thisReport)
docRef.updateData(data) { error in
if let error = error {
print("Error updating document: (error)")
} else {
print("Document successfully updated")
}
}
}
作为参考,这是如何在Firebase中保存和上传报告到数据库的。
// FSR REPORT POSTING
public func insert(
reportPost: ReportPost,
email: String,
completion: @escaping (Bool) -> Void
) {
let userEmail = email
.replacingOccurrences(of: ".", with: "_")
.replacingOccurrences(of: "@", with: "_")
let data = [
"id": reportPost.identifier,
"title": reportPost.title,
"timestamp1": reportPost.timestamp1,
"address": reportPost.address,
"customerPO": reportPost.customerPO,
"authNum": reportPost.authNum,
"contactName": reportPost.contactName,
"contactPhone": reportPost.contactPhone,
"modelNum": reportPost.modelNum,
"serialNum": reportPost.serialNum,
"addInfo": reportPost.addInfo,
"equipProblem": reportPost.equipProblem,
"action": reportPost.action,
"followUp": reportPost.followUp,
"techName1": reportPost.techName1,
"techName2": reportPost.techName2,
"techName3": reportPost.techName3,
"techName4": reportPost.techName4,
"timestamp2": reportPost.timestamp2,
"timestamp3": reportPost.timestamp3,
"timestamp4": reportPost.timestamp4,
"milesTraveled1": reportPost.milesTraveled1,
"milesTraveled2": reportPost.milesTraveled2,
"milesTraveled3": reportPost.milesTraveled3,
"milesTraveled4": reportPost.milesTraveled4,
"travelTime1": reportPost.travelTime1,
"travelTime2": reportPost.travelTime2,
"travelTime3": reportPost.travelTime3,
"travelTime4": reportPost.travelTime4,
"siteTime1": reportPost.siteTime1,
"siteTime2": reportPost.siteTime2,
"siteTime3": reportPost.siteTime3,
"siteTime4": reportPost.siteTime4,
"serviceType1": reportPost.serviceType1,
"serviceType2": reportPost.serviceType2,
"serviceType3": reportPost.serviceType3,
"serviceType4": reportPost.serviceType4,
"timeTotal1": reportPost.timeTotal1,
"timeTotal2": reportPost.timeTotal2,
"timeTotal3": reportPost.timeTotal3,
"timeTotal4": reportPost.timeTotal4,
"partNum1": reportPost.partNum1,
"partNum2": reportPost.partNum2,
"partNum3": reportPost.partNum3,
"partNum4": reportPost.partNum4,
"quantity1": reportPost.quantity1,
"quantity2": reportPost.quantity2,
"quantity3": reportPost.quantity3,
"quantity4": reportPost.quantity4,
"price1": reportPost.price1,
"price2": reportPost.price2,
"price3": reportPost.price3,
"price4": reportPost.price4,
"priceTotal1": reportPost.priceTotal1,
"priceTotal2": reportPost.priceTotal2,
"priceTotal3": reportPost.priceTotal3,
"priceTotal4": reportPost.priceTotal4,
]
database
.collection("users")
.document(userEmail)
.collection("reports")
.document(reportPost.identifier)
.setData(data) { error in
completion(error == nil)
}
}
当报告第一次插入时,它被存储在这个路径
database.collection("users")
.document(userEmail)
.collection("reports")
.document(reportPost.identifier)
.setData(data)
users/the_email/reports/some id
但是当你试图更新报告时它在这个路径
database.collection("reports")
.document(thisReport)
.updateData(data)
database/reports/some id
这是两个不同的位置
要更新数据,它需要指向相同的文档引用。所以数据需要在最初写入
的相同位置进行更新database.collection("users")
.document(userEmail)
.collection("reports")
.document(reportPost.identifier)
.updateData(data) //<- same path as it was initially
作为旁注,documentId既存储为documentId,也存储在文档的"id"中。菲尔德,没有理由这么做。documentId是静态的,如果它是已知的,您可以直接获得该数据,而无需查询。
我还建议不要使用用户的电子邮件作为文档编号;用户的电子邮件可以更改,如果发生这种情况,您将无法找到报告。另外,如果你想更新它,你需要找到整个数据库中出现的所有旧邮件,读取它和它的子数据,删除它,重写它。真痛苦。
同样,用_代替@和。在电子邮件地址中可能会工作到某一点,但如果想要得到那个电子邮件地址,可以在地址中有多个_;你怎么知道哪个_是@,哪个是电子邮件地址的一部分呢?
some_person@thing.com -> some_person_thing_com = some@person_thing.com?
编辑
根据问题,假设有一系列报告,1)用户之间共享2)创建用户可以编辑他们自己的报告
这里有一个存储报告的选项
reports (collection)
document_0 //a document with an auto-generated documentId
created_by_uid: "uid_0"
report_info: "some info about this report, fields etc"
document_1
created_by_uid: "uid_1"
report_info: "some info about this report"
报表集合可以被任何用户读取,满足条件1。使用uid_0获取用户创建的报告很容易,因为可以对报告集合运行一个简单的查询,其中created_by_uid = uid_0。
下面的代码包含一个对象来保存报告数据:documentId report_info(报告数据)和一个字段来跟踪谁创建了报告。假设uid_0用户登录并想要编辑一个报告。我们将加载uid_0创建的所有报告,并将它们存储在一个数组中:
class ReportClass {
var id = ""
var report_info = ""
var created_by_uid = ""
}
var reportArray = [ReportClass]()
func readReports(forUid: String) { //pass in uid_0
let reportsCollection = self.db.collection("reports")
reportsCollection.whereField("created_by_uid", isEqualTo: forUid)
reportsCollection.getDocuments(completion: {documentSnapshot, error in
for doc in documentSnapshot!.documents {
//note we don't need the created_by_uid because it's not going to change
let report = ReportClass()
//keep track of the document Id
report.id = doc.documentID as! String
//the report info which the user is changing
report.report_info = doc.get("report_info") as! String
self.reportArray.append(report)
}
})
}
现在报告呈现给用户,因此他们可以选择一个并编辑它。保存后,我们使用用户输入的新数据更新ReportClass对象report_info字段,并将该对象传递给一个函数以更新该报告
func updateReport(theReport: ReportClass) {
let reportsCollection = self.db.collection("reports")
let thisReport = reportsCollection.document(theReport.id)
//the report document path is reports/documentId
thisReport.updateData(["report_info": theReport.info]) //only update the report_info field
}
这里的关键是我们加载并存储用户报告,并在对象中保留报告文档id。跟踪到报告
的路径reports/report id/id, report_info and created_by_uid fields
然后,当报告准备好编写时,我们从存储在对象中的documentId派生路径,因此路径是相同的。
我做了很多冗长的工作,但您应该使用可编码对象,因为它使填充它们变得很容易
参见在Swift中映射Firestore数据