简体   繁体   English

将文档的文档 ID 添加到其自己的 Firestore 文档 - Swift 4

[英]Add a Document's Document ID to Its Own Firestore Document - Swift 4

How do I go about adding the document ID of a document I just added to my firestore database, to said document?如何将刚刚添加到我的 firestore 数据库中的文档的文档 ID 添加到所述文档?

I want to do this so that when a user retrieves a "ride" object and chooses to book it, I can know which specific ride they've booked.我想这样做,以便当用户检索“乘车”对象并选择预订它时,我可以知道他们预订了哪个特定的乘车。

The problem that i'm facing is that you can't get the document ID until after it's created, so the only way to add it to said document would be to create a document, read its ID, then edit the document to add in the ID.我面临的问题是在创建文档之前您无法获取文档 ID,因此将其添加到所述文档的唯一方法是创建文档,读取其 ID,然后编辑文档以添加身份证。 At scale this would create twice as many server calls as desired.在规模上,这将根据需要创建两倍的服务器调用。

Is there a standard way to do this?有没有标准的方法来做到这一点? Or a simple solution to know which "ride" the user booked and edit it accordingly in the database?或者一个简单的解决方案来知道用户预订了哪个“乘车”并在数据库中相应地对其进行编辑?

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.
        }
    }
}

While there is a perfectly fine answer, FireStore has the functionality you need built in, and it doesn't require two calls to the database.虽然有一个完美的答案,但 FireStore 具有您需要的内置功能,并且不需要两次调用数据库。 In fact, it doesn't require any calls to the database.事实上,它不需要对数据库进行任何调用。

Here's an example这是一个例子

    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

See the documentation Add a Document for more info.有关更多信息,请参阅文档添加文档

In some cases, it can be useful to create a document reference with an auto-generated ID, then use the reference later.在某些情况下,使用自动生成的 ID 创建文档引用,然后稍后使用该引用会很有用。 For this use case, you can call doc():对于此用例,您可以调用 doc():

You may want to consider a slightly different approach.您可能需要考虑一种稍微不同的方法。 You can obtain the document ID in the closure following the write as well.您也可以在写入后的闭包中获取文档 ID。 So let's give you a cool Ride (class)所以让我们给你一个酷骑(类)

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
    }
}

and then some code to create a ride, write it out and leverage it's auto-created documentID然后一些代码来创建骑行,写出来并利用它的自动创建的文档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
        }
    }

I believe that if you use Swift's inbuilt ID generator, called UUID , provided by the Foundation Framework, this will let you do what you want to do.我相信如果你使用 Swift 内置的 ID 生成器,称为UUID ,由Foundation Framework 提供,这会让你做你想做的事。 Please see the below code for my recommended changes.请参阅以下代码以了解我建议的更改。 Also by doing it this way, when you first initialise your "Ride" struct, you can generate its ID variable then, instead of doing it inside the function.同样通过这种方式,当您第一次初始化“Ride”结构时,您可以生成它的 ID 变量,而不是在函数内部进行。 This is the way I generate unique ID's throughout my applications and it works perfectly!这就是我在整个应用程序中生成唯一 ID 的方式,而且效果很好! Hope this helps!希望这可以帮助!

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)
        }
    }
}

This is my solution which works like a charm这是我的解决方案,它就像一个魅力

    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(()))
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM