在 Firestore 中使用 Codable 时如何获取文档 ID?

How can I get the document ID when using Codable in Firestore?

我想获取文档 ID 以便在解码后使用它来编辑和删除文档。我该怎么做?

我的模特:

struct MoodRecord: Codable, Hashable, Identifiable {
   @DocumentID var id: String?
   let user: String
   let date: String
   let time: String
   let mood: Int
}

我的函数:

class func getRecords <T: Decodable> (
    reference: CollectionReference,
    type: T.Type,
    completion: @escaping (Result<[T], Error>) -> Void
) {
    reference.whereField("user", isEqualTo: AuthManager.shared.getUserId() ?? "")
        .getDocuments { snapshot, error in
        if let documents = snapshot?.documents {
            do {
                let records: [T] = try documents.map { try [=11=].decoded(type: T.self) }
                completion(.success(records))
            } catch let error {
                completion(.failure(error))
            }
        } else if let error = error {
            completion(.failure(error))
        }
    }
}

我的解码器:

extension QuerySnapshot {

    func decoded <T: Decodable> (type: T.Type) throws -> [T] {
        let objects: [T] = try documents.map { try [=12=].decoded(type: T.self) }
        return objects
    }
}

extension QueryDocumentSnapshot {

    func decoded <T: Decodable> (type: T.Type) throws -> T {
        let jsonData = try JSONSerialization.data(withJSONObject: data(), options: [])
        let object = try JSONDecoder().decode(type.self, from: jsonData)
        return object
    }
}

我在 Firestore 中仅使用自动 ID,并希望在此任务中使用它们。我可以这样做吗?

您可以使用 Firestore 的 Codable 支持来映射文档 ID。无需实施自定义解码器 - 我们已为您完成所有艰苦的工作。

方法如下。

1。为您的数据创建模型

你已经这样做了。查看 MoodRecord 结构中的属性,我假设您想使用 datetime 来跟踪时间戳,并使用 mood 来捕获枚举的值。我相应地更新了结构:

struct MoodRecord: Codable, Hashable, Identifiable {
  @DocumentID var id: String?
  var user: String
  var date: Date
  var time: Date
  var mood: Mood
}

enum Mood: String, Codable {
  case great
  case ok
  case good
  case bad
  case terrible
}

2。使用 Codable

映射数据

获取 Firestore 文档并将它们映射到 Swift 结构成为 one-liner 感谢 Codable:

docRef.getDocument(as: MoodRecord.self) { result in
  // handle result
}

这是获取单个文档的完整代码片段:

private func fetchMoodRecord(documentId: String) {
  let docRef = db.collection("moodrecords").document(documentId)
  
  docRef.getDocument(as: MoodRecord.self) { result in
    switch result {
    case .success(let moodRecord):
      // A MoodRecord value was successfully initialized from the DocumentSnapshot.
      self.moodRecord = moodRecord
      self.errorMessage = nil
    case .failure(let error):
      // A MoodRecord value could not be initialized from the DocumentSnapshot.
      self.errorMessage = "Error decoding document: \(error.localizedDescription)"
    }
  }
}

3。更新文档

要使用 Codable 更新文档,请使用以下代码片段:

func updateMoodRecord(moodRecord: MoodRecord) {
  if let id = moodRecord.id {
    let docRef = db.collection("moodRecords").document(id)
    do {
      try docRef.setData(from: moodRecord)
    }
    catch {
      print(error)
    }
  }
}

4.Adding 新文档

添加新文档更容易:

func addMoodRecord(moodRecord: MoodRecord) {
  let collectionRef = db.collection("moodRecords")
  do {
    let newDocReference = try collectionRef.addDocument(from: moodRecord)
    print("Mood record stored with new document reference: \(newDocReference)")
  }
  catch {
    print(error)
  }
}

更多

要详细了解如何使用 Swift 的 Codable 协议映射 Firestore 文档,包括如何映射日期、时间、颜色、枚举等高级数据类型,如何使用快照侦听器获取数据,以及如何处理映射过程中可能发生的任何错误,请查看 Mapping Firestore Data in Swift - The Comprehensive Guide and the accompanying sample project on GitHub