4

I have a simple Firestore transaction that reads to verify the existence of a document first, and if it doesn't exist, does some write operations.

Code snippet looks something like this

Firestore.firestore().runTransaction({ (transaction, errorPointer) -> Void in let snapshot: DocumentSnapshot // First check if user already exists. let userRef = firestore.document("users/\(user.uid)") do { try snapshot = transaction.getDocument(userRef) } catch let fetchError as NSError { errorPointer?.pointee = fetchError return } if !snapshot.exists { // Document doesn't exist. Start write operation... ... 

It seems that getDocument does not return a valid snapshot when the document doesn't exist and instead throws an error. I don't want to rely on the error to conclude that the doc doesn't exist (as it can get muddled with other errors).

What would be the proper way to verify a document's existence within a Firestore transaction?

1 Answer 1

4

Well, you can try doing something like this:

Firestore.firestore().runTransaction({ (transaction, errorPointer) -> Void in let snapshot: DocumentSnapshot if let snapshot = try? transaction.getDocument(userRef) { if snapshot.exists { // Snapshot already exists! return } } print("Document doesn't exist. Let's get to work!") // Perform write operations here ... 

Although depending on what you're looking to do, it might be easier to enforce this with security rules.

For example, the following rules will allow you to create a new user object, but never overwrite it.

match /users/{userID} { allow create: if request.auth.uid == userID; allow update: if false; } 

Then you could just try to set the user object every time, and it would only succeed the first time. But, obviously, this only works if you never actually want your client to update the user object in the future.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you. My concern was whether relying on getDocument throwing an error is the right thing to do to determine that the document doesn't exist. Currently if the document doesn't exist, it won't even get to the snapshot.exists if statement. It will simply throw an error. This behavior with getDocument on transactions is different from the behavior getDocument returns on a DocumentReference (where it properly reads the snapshot and the exists property can be used as documented). I found the difference between the two confusing.
@jayOrange same here, has your understanding on this changed?
On a similar note, it would be great to know that the error is thrown if and only if the document does not exist. If any other errors are thrown in the presence of the document in question, the code might perform an unwanted overwrite.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.