How can I tell if I value already exists in Firebase Firestore? - swift

I would like to receive a bool letting me know if my document has a Wasiyyah or not..
What I've tried:
Firestore.firestore().collection(user!.uid).document(docID).value(forKey: "Wasiyyah")
Which only crashes every time, so there must be something I'm not understanding here.

There isn't any function to check if a field exists in a document. You'll have to fetch the document and check for it's existence:
let docRef = Firestore.firestore().collection(user!.uid).document(docID)
docRef.getDocument { (document, error) in
if let document = document, document.exists {
let data = document.data()
// Check if the field exists in data
} else {
print("Document does not exist")
}
}

Related

Get the Data of any user according to ID

so, here how can i get the data of any user according to uids ?
From your screenshot we can see that the value of the field uid is also used as the ID of the user's Firestore document (which is a very good approach :-))
Therefore you can simply query the document of a specific user as follows:
let docRef = db.collection("users").document(uid) // We use the uid to define the Document Reference
docRef.getDocument { (document, error) in
if let document = document, document.exists {
let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
print("Document data: \(dataDescription)")
} else {
print("Document does not exist")
}
}

Firebase/Firestore: Value of type 'DocumentReference' has no member 'get'

I am trying to access a document and get value from the fields so I can login as a user and retrieve that user data. I have the following code that will not compile because I keep getting the error 'Value of type 'DocumentReference' has no member 'get'. Please help!
Your newDoc is a DocumentReference object, which is nothing more than a reference to a (potential) document in the database.
To load the document from the database you need to call getdocument() on the reference, as shown in this snippet from the documentation:
let docRef = db.collection("cities").document("SF")
docRef.getDocument { (document, error) in
if let document = document, document.exists {
let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
print("Document data: \(dataDescription)")
} else {
print("Document does not exist")
}
}
The data is only available within the completion handler, as shown above. Trying to access it outside of there will lead to timing problems, as the data is loaded asynchronously.

refrence to document ID

#IBAction func NextButtonTapped(_ sender: Any) {
//validate the fileds
let Error = validateFields()
if Error != nil {
// there is somthing wrong with the fields show error message
showError(Error!)
}
else {
// create cleaned versions of the data
let Password = PasswordTextField.text!.trimmingCharacters(in:
.whitespacesAndNewlines)
let Email = EmailTextField.text!.trimmingCharacters(in:
.whitespacesAndNewlines)
let Firstname = FirstnameTextField.text!.trimmingCharacters(in:
.whitespacesAndNewlines)
let Lastname = LastnameTextField.text!.trimmingCharacters(in:
.whitespacesAndNewlines)
let Age = AgeTextField.text!.trimmingCharacters(in:
.whitespacesAndNewlines)
// create the user
Auth.auth().createUser(withEmail: Email, password: Password) {
(results, Err) in
// check for errors
if Err != nil {
// there was an error creating the user
self.showError("Error creating user")
}
else {
// user was created succesfully store user info
let db = Firestore.firestore()
db.collection("users").document(results!.user.uid).setData(["first
name":Firstname, "last name":Lastname, "age":Age,
"uid":results!.user.uid]) { (Error) in
if Error != nil {
// show error message
self.showError("error saving user data")
}
}
//transition to the home screen
self.transitionToHome()
}
}
}
}
So basically here I am authenticating the user on firebase. (I made
the document ID = the user ID) then I am entering the users info
into the firebase database into a document where its ID is also
equal to the users ID from when they are authenticated. Now what I
am trying to do is to create or get a reference to the document ID
where some of the users info is already stored like name, last name,
age... so I can later add/merge more info into that same document
the name, last name and age is stored under. This is how I am trying
to merge the info together in a diffrent view controller
db.collection("users").document(*******).setData(["middle
Name":Middlename, "favourite colour":Favouritecolour], merge: true)
{ (Error) in
if Error != nil {
// show error messgae
self.showError("error saving user data")
}
}
Where I put "*******" is where I am supposed to reference the
document ID so I can merge/add this info into the same document as
the other users information where the name, last name and age is
stored.
The code I showed you and asked about earlier on how to get a
document ID from, was code I found on stack overflow where they guy
had a similar problem as mine. He was trying to access something out
of his document but I am just trying to create a reference to the
document ID.
The code form earlier:
func getDocument() {
//get specific document from current user
let docRef =
Firestore.firestore().collection("users").document(Auth.auth().currentUs er?.uid ?? "")
//get data
docRef.getDocument { (document, Error) in
if let document = document, document.exists {
let dataDescription = document.data()
print(dataDescription?["uid"])
} else {
print("Document does not exist")
}
}
}
But I don't know if this code will help me, I just thought it might
because its also accessing the document, thats why I though it might
be my answer to getting the document ID.
So basically my question is what do I need to do wether its adding
to the code I found on this site, or if I have to write my own code,
so I can get a reference to the Document ID where my name, last name
and Age is stored, so I can merge more Info into that document
Thank You Very Much!!!
To print the document ID do something like this:
let docRef = Firestore.firestore().collection("users").document(Auth.auth().currentUser?.uid ?? "")
// Get data
docRef.getDocument { (document, error) in
if let document = document, document.exists {
let dataDescription = document.data()
print(dataDescription?["firstname"])
print(document.documentID)
} else {
print("Document does not exist")
}
}
I highly recommend spending some time in the Firestore documentation, as this is covered in there under getting multiple documents from a collection

Can I use a Swift String Variable to get a Firebase document for a user?

I am trying to read some data from my database but I only want to read the data for one user instead reading the data from all Users.
I tried using the variable userEmail to list only a certain users code.
let userEmail = String((Auth.auth().currentUser?.email)!)
func readArray() {
print(userEmail)
let docRef = Firestore.firestore().collection("users").document("\(userEmail)")
//let docRef = db.collection("cities").document("SF")
docRef.getDocument { (document, error) in
if let document = document, document.exists {
let dataDescription = document.data().map(String.init(describing:)) ?? "nil"
print("Document data: \(dataDescription)")
} else {
print("Document does not exist")
}
}
}
I can get the user's information if I type out their user email as "test#gmail.com" but I know this won't work for other users with different login emails.
enter image description here
The issue fixed itself. Just had to reset my internet connection. This is very odd but it turns out that you can use variables to find your specific document.

Firebase Cloud Firestore - Accessing a collection from a reference

High level: In Cloud Firestore, I have two collections. fl_content and fl_files. Within fl_content, I am trying to access fl_files.
Detailed: In fl_content, each document has a field called imageUpload. This is an array of Firebase Document References. (a path to fl_files that I need to access.)
Here's my query for fl_content, in which I am accessing imageUpload reference:
let docRef = Firestore.firestore().collection("fl_content").document(item.id)
docRef.getDocument { (document, error) in
if let document = document, document.exists {
let property = document.get("imageUpload")
print("PROPERTY \(property!)")
}
}
This prints the following to the console:
PROPERTY Optional(<__NSArrayM 0x60000281d530>(
<FIRDocumentReference: 0x600002826220>
)
)
With this array of Document References, I need to get to fl_files.
This is the part I am having trouble with.
Attempts:
Within the if let statement, I tried accessing fl_files by casting property as a DocumentReference.
let docRef = Firestore.firestore().collection("fl_content").document(item.id)
docRef.getDocument { (document, error) in
if let document = document, document.exists {
let property = document.get("imageUpload") as? DocumentReference
print("PROPERTY \(property!)")
let test = Firestore.firestore().collection("fl_files").document(property)
}
}
Cannot convert value of type 'DocumentReference?' to expected argument type 'String'
let docRef = Firestore.firestore().collection("fl_content").document(item.id)
docRef.getDocument { (document, error) in
if let document = document, document.exists {
let property = document.get("imageUpload") as! DocumentReference
let test = Firestore.firestore().collection("fl_files").document(property[0].documentID)
print("TEST \(test)")
}
}
Value of type 'DocumentReference' has no subscripts
let docRef = Firestore.firestore().collection("fl_content").document(item.id)
docRef.getDocument { (document, error) in
if let document = document, document.exists {
let property = document.get("imageUpload") as! DocumentReference
let test = Firestore.firestore().collection("fl_files").document(property.documentID)
print("TEST \(test)")
}
}
Could not cast value of type '__NSArrayM' (0x7fff87c50980) to 'FIRDocumentReference' (0x10f6d87a8).
2020-02-05 12:55:09.225374-0500 Database 1[87636:7766359] Could not cast value of type '__NSArrayM' (0x7fff87c50980) to 'FIRDocumentReference' (0x10f6d87a8).
Getting closer!
let docRef = Firestore.firestore().collection("fl_content").document(item.id)
docRef.getDocument(completion: { document, error in
if let err = error {
print(err.localizedDescription)
return
}
let imageUpload = document?["imageUpload"] as? NSArray ?? [""]
print("First Object \(imageUpload.firstObject!)")
})
This prints: First Object <FIRDocumentReference: 0x600001a4f0c0>
Here are two screenshots to help illustrate what the Firestore database looks like..
Ultimately, I need to get to the file field within fl_files. How do I access this from the imageUpload DocumentReference?
Finally got it, thanks to the help of #Jay and #Emil Gi.
The "A-HA" moment came from Emil Gi's comment: All I can say is that if you successfully get element of DocumentReference type, then it must have an id property, which you can extract and query collection by document id.
let imageUploadReference = item.imageUpload.first as? DocumentReference
let docRef = Firestore.firestore().collection("fl_files").document(imageUploadReference!.documentID)
docRef.getDocument(completion: { document, error in
if let err = error {
print(err.localizedDescription)
return
}
let fileNameField = document?.get("file") as! String
print("File name from fl_files \(fileNameField)")
})
Once I finally had access to the corresponding "file", it was very simple to download the full URL of the image to the imageView.
I appreciate all of your help!!!
Here's some sample code that shows how to read and print out any of the fields values and also how to read the imageUpload field (an array) and print out the first element's value.
I've included both ways to read data from a document because I believe it answers both parts of the question: how to get the array field imageUpload and then access the first element within that array and how to get the value of the file field within fl_files.
Assuming this points to the correct document:
let docRef = Firestore.firestore().collection("fl_content").document(item.id)
this code will read two fields from the document being pointed to: imageUpload (an array) and fl_id (a String)
docRef.getDocument(completion: { document, error in
if let err = error {
print(err.localizedDescription)
return
}
print( document!.data() ) //for testing to see if we are getting the fields
//how to read an array and access it's elements
let imageUploadArray = document?["imageUpload"] as? Array ?? [""]
if let url = imageUploadArray.first {
print(url)
}
//this is also valid for reading the imageUpload field array
//let anArray = document?.get("imageUpload") as? Array ?? [""]
//if let url = anArray {
// print(url)
//}
//how to read a single field, like file within fl_files
let someId = document?.get("fl_id") as! String //example of reading a field
print(someId)
})
Edit:
It appears the objects stored in the imageUpload array are references not strings. As an example of how to access them... here's the code
let refArray = document?.get("imageUpload") as? [DocumentReference] ?? []
for docRef in refArray {
print(docRef.path) //prints the path to the document at this ref
}