【问题标题】:Add a Document's Document ID to Its Own Firestore Document - Swift 4将文档的文档 ID 添加到其自己的 Firestore 文档 - Swift 4
【发布时间】:2019-06-15 12:19:25
【问题描述】:

如何将刚刚添加到 Firestore 数据库的文档的文档 ID 添加到所述文档?

我想这样做,以便当用户检索“乘车”对象并选择预订时,我可以知道他们预订了哪个具体的乘车。

我面临的问题是,在创建文档 ID 之前,您无法获取文档 ID,因此将其添加到所述文档的唯一方法是创建一个文档,读取其 ID,然后编辑该文档添加ID。在规模上,这将创建两倍于所需的服务器调用。

有没有标准的方法来做到这一点?还是一个简单的解决方案来了解用户预订了哪个“骑行”并在数据库中进行相应的编辑?

struct Ride {
    var availableSeats: Int
    var carType: String
    var dateCreated: Timestamp
    var ID: String // How do I implement this?
}


func createRide(ride: Ride, completion: @escaping(_ rideID: String?, _ error: Error?) -> Void) {
    // Firebase setup
    settings.areTimestampsInSnapshotsEnabled = true
    db.settings = settings

    // Add a new document with a generated ID
    var ref: DocumentReference? = nil
    ref = db.collection("rides").addDocument(data: [
        "availableSeats": ride.availableSeats,
        "carType": ride.carType,
        "dateCreated": ride.dateCreated,
        "ID": ride.ID,
    ]) { err in
        if let err = err {
            print("Error adding ride: \(err)")
            completion(nil, err)
        } else {
            print("Ride added with ID: \(ref!.documentID)")
            completion(ref?.documentID, nil)
            // I'd currently have to use this `ref?.documentID` and edit this document immediately after creating. 2 calls to the database.
        }
    }
}

【问题讨论】:

    标签: ios swift firebase google-cloud-firestore


    【解决方案1】:

    虽然有一个完美的答案,但 FireStore 具有您需要的内置功能,并且不需要两次调用数据库。事实上,它不需要对数据库进行任何调用。

    这是一个例子

        let testRef = self.db.collection("test_node")
        let someData = [
            "child_key": "child_value"
        ]
    
        let aDoc = testRef.document() //this creates a document with a documentID
        print(aDoc.documentID) //prints the documentID, no database interaction
        //you could add the documentID to an object etc at this point
        aDoc.setData(someData) //stores the data at that documentID
    

    有关详细信息,请参阅文档 Add a Document

    在某些情况下,使用 自动生成的 ID,然后使用参考。对于这个用例, 你可以调用 doc():

    您可能需要考虑一种稍微不同的方法。您也可以在写入后的闭包中获取文档 ID。所以让我们给你一个很酷的旅程(类)

    class RideClass {
        var availableSeats: Int
        var carType: String
        var dateCreated: String
        var ID: String
    
        init(seats: Int, car: String, createdDate: String) {
            self.availableSeats = seats
            self.carType = car
            self.dateCreated = createdDate
            self.ID = ""
        }
    
        func getRideDict() -> [String: Any] {
            let dict:[String: Any] = [
                "availableSeats": self.availableSeats,
                "carType": self.carType,
                "dateCreated": self.dateCreated
            ]
            return dict
        }
    }
    

    然后是一些代码来创建一个旅程,写出来并利用它的自动创建的文档ID

        var aRide = RideClass(seats: 3, car: "Lincoln", createdDate: "20190122")
    
        var ref: DocumentReference? = nil
        ref = db.collection("rides").addDocument(data: aRide.getRideDict() ) { err in
            if let err = err {
                print("Error adding document: \(err)")
            } else {
                aRide.ID = ref!.documentID
                print(aRide.ID) //now you can work with the ride and know it's ID
            }
        }
    

    【讨论】:

    • 好像是双重读写。这个电话会严重打击免费轮胎。有什么解决办法吗?
    • @EngineSense 不确定您的意思。在我回答的第一部分,根本没有读或写。在第二个示例中,它是单次写入。什么是免费轮胎,既然是单写,为什么会受到重创?
    【解决方案2】:

    我相信,如果你使用 Swift 的内置 ID 生成器,称为 UUID,由 Foundation 框架提供,这会让你做你想做的事。请参阅下面的代码以了解我建议的更改。同样通过这种方式,当您第一次初始化“Ride”结构时,您可以生成它的 ID 变量,而不是在函数内部进行。这是我在整个应用程序中生成唯一 ID 的方式,而且效果很好!希望这会有所帮助!

    struct Ride {
        var availableSeats: Int
        var carType: String
        var dateCreated: Timestamp
        var ID: String
    }
    
    
    func createRide(ride: Ride, completion: @escaping(_ rideID: String, _ error: Error?) -> Void) {
        // Firebase setup
        settings.areTimestampsInSnapshotsEnabled = true
        db.settings = settings
    
        // Add a new document with a generated ID
        var ref: DocumentReference? = nil
        let newDocumentID = UUID().uuidString
        ref = db.collection("rides").document(newDocumentID).setData([
            "availableSeats": ride.availableSeats,
            "carType": ride.carType,
            "dateCreated": ride.dateCreated,
            "ID": newDocumentID,
        ], merge: true) { err in
            if let err = err {
                print("Error adding ride: \(err)")
                completion(nil, err)
            } else {
                print("Ride added with ID: \(newDocumentID)")
                completion(newDocumentID, nil)
            }
        }
    }
    

    【讨论】:

    • 完美解决方案!这个UUID 函数会创建两次相同的 id 吗?
    • 别担心!不,只要你在同一个函数中重新使用“let newDocumentID = UUID().uuidString”来做其他事情,比如新的文档参考,你应该绝对没问题! ?
    【解决方案3】:

    这是我的解决方案,就像一个魅力

        let opportunityCollection = db.collection("opportunities")
        let opportunityDocument = opportunityCollection.document()
        let id = opportunityDocument.documentID
    
        let data: [String: Any] = ["id": id,
                                   "name": "Kelvin"]
    
        opportunityDocument.setData(data) { (error) in
            if let error = error {
                completion(.failure(error))
            } else {
                completion(.success(()))
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-22
      • 1970-01-01
      • 2021-07-20
      • 2022-06-14
      相关资源
      最近更新 更多