Learn Courses My Dashboard

Firebase subcollections

how do I fetch subcollcetions and also send sub collections query data

— user (collection)

         |
         --- user uid (documents)
              |
              --- basic_data (sub-collection)
                    |
                    --- contactinfo (document)

like this

If I can paraphrase what your firebase structure is:

You have a collection named “user” which had a documentID which is the currentUser.uid (from authentication) in which you have a sub collection named “basic-data” which has an Auto Generated ID which has fields related to the user like:
firstname
lastname
email
phone
etc

Does that sound about right?

yes boss

In my sample data I have it structured as you have described.

Assuming that you are the currently logged in user and you have an associated user record containing some basic-data then this is the code that I used in order to retrieve those details.

I am assuming that you have some understanding of how Firebase works.

    func getLoggedInUser() -> String {
        Auth.auth().currentUser?.uid ?? ""
    }

   func getUserDetails() {
        // Get the current userId which will correspond to the user document id
        let userId = getLoggedInUser()
        // get a reference to the database
        let db = Firestore.firestore()
        // establish the collection path to the basic-data items
        let user = db.collection("user").document(userId).collection("basic-data")

        // initiate the fetch
        user.getDocuments { snapshot, error in
            // Check for errors
            if let error = error {
                print(error.localizedDescription)
            } else {
                if let snapshot = snapshot {
                    // We have data retrieved so process it.
                    for doc in snapshot.documents {
                        let firstName = doc["firstname"] as? String
                        let lastName = doc["lastname"] as? String
                        let email = doc["email"] as? String
                        let phoneNumber = doc["phone"] as? String

                        //  Do something with the property data retrieved.

                    }
                }
            }
        }
    }

The function getLoggedInUser() is just a re-usable function that you would normally have elsewhere in your project.

The getUserDetails() function I hope is somewhat understandable. Let me know if there is anything that you do not understand.

I don’t want use authentication how do I generate the userid please

sorry the first function is to automatically generate a userid then there is no need to pass an id in the model right?

I don’t want to use an authentication userid I want use a id in the model

hello please I still need help

Are you presenting users with a login screen in your App?

Yes but I don’t want to do that right now I just want to learn how to fetch and post sub collections when I use the get documents it doesn’t fetch the sub collections that’s why I’m asking

Users-genratedid-basicdata-generatedid-(name)
generatedid-(name)

So I want to fetch those name and pass it on a list same users same basic data but different if under basic data

In that case the simple answer is to create a “user” collection in your database and assign a document ID manually where you would ultimately use a documentID that is the currentUser.uid. Just make up some alpha numeric string that you can remember and then in the code I provided, set userId to that string and just ignore the other function getLoggedInUser()

For example
let userId = "thedogatemyhomework"

Since the code I have provided you is dependant on a Firebase record manually created, you need to do that in your database and then run the code.


You mean this generatedid should be passed like geoggeduswr()


Like this

Yes. If you have already created the collection with AutoID and sub-collection then copy the documentID as you have done.

When you post images of your code, use the built in screenshot app rather than take a photograph. Photographs of code are sometimes unclear and very hard to view.

With the Mac ScreenShot App, you can capture the entire window, the entire screen or a section of the screen.

If you just want a small section, press Shift + Command + 4 which will change your mouse pointer into a set of crosshairs. Click and drag diagonally across the screen to capture the section you want. When you let go of the mouse button, the image will be saved to your Desktop and will be named something like “Screen Shot YYYY-MM-DD at HH.MM.SS am/pm”.

Other screenshot selection options are available by pressing Shift + Command + 5. An options bar will appear near the bottom of the screen. You can even video record your screen.

thank you what about posting to firebase and update plus delete function and can you still brief explain the authentication linking of the id with sub collections as your code stated earlier thank you

any time I post it crashes can you help please

Been a bit occupied here. We are probably in quite different time zones.

Let me put together some code to create a record and then I’ll write some to Delete and Update.

Might be a while so relax.

To create a new “user” record was not as straight forward as I had hoped. I am using a collection named “user” and I note that your collection name is “collections”. That’s not particularly descriptive so in my examples I will stick to the high level collection being named “user”.

What you cannot do is have a document with just a collection associated with it. You must have at least one field as part of that first level document so when I created my new “user” entry I added a field named “date” and set the date to the current date usage Date(). You will see what I am talking about in the code below.

I have generated a 20 character random string courtesy of this website:
https://www.random.org/strings/
Quite handy really.

Here is the code to create a new user record:

    func createUserDetails() {

        let docId = "KcC7h8BhzxewFkNQbolk"

        let firstName = "Ben"
        let lastName = "Dover"
        let email = "ben@somedomain.com"
        let phoneNumber = "01234567890"

        let db = Firestore.firestore()

        let userCollection = db.collection("user")

        userCollection.document(docId).setData(["date": Date()])
        userCollection.document(docId)
            .collection("basic-data")
            .document("currentUser")
            .setData(["firstname": firstName,
                      "lastname": lastName,
                      "email": email,
                      "phone": phoneNumber])
    }

The 20 character random document ID is assigned to docId.
You will note that I have used a documentId of currentUser for the basic-data collection document ID rather than letting it create a document ID using AutoID (the default). The reason being that it would have made it horribly messy to update the basic-data details (ie, change the phone number for example) since you would need to perform a database query to get the basic-data documentId and then use that in an updateData() method. Technically you would allow the documentID to be Auto generated by Firebase and perform a query but there isn’t time for me to do that right now.

To update the user details (let’s say just the phone number), this is how you would go about it:

    func updateUserDetails() {

        let docId = "KcC7h8BhzxewFkNQbolk"
        let newPhone = "0987654321"

        let db = Firestore.firestore()

        let userCollection = db.collection("user")

        userCollection.document(docId)
            .collection("basic-data")
            .document("currentUser")
            .updateData(["phone" : newPhone])
    }

and to delete that entire user record is pretty simple:

    func deleteUserDetail() {

        let docId = "KcC7h8BhzxewFkNQbolk"

        let db = Firestore.firestore()

        let userCollection = db.collection("user")

        userCollection.document(docId).delete()

    }

it crashed when fetched, the posted data but the posting appears on firebase

What do you mean? Do you mean that you used the getUserDetails() code to fetch the new one you created?

In the case of the sample create, update and delete code that I provided above, the corresponding getUserDetails() code would need to be:

    func getUserDetails() {

        // Get the current userId which will correspond to the user document id
        let userId = "KcC7h8BhzxewFkNQbolk" // Same document Id as used in the createUserDetails()

        // get a reference to the database
        let db = Firestore.firestore()

        // establish the collection path to the basic-data items
        let user = db.collection("user").document(userId).collection("basic-data")

        // initiate the fetch
        user.getDocuments { snapshot, error in
            // Check for errors
            if let error = error {
                print(error.localizedDescription)
            } else {
                if let snapshot = snapshot {
                    // We have data retrieved so process it.
                    for doc in snapshot.documents {
                        let firstName = doc["firstname"] as? String
                        let lastName = doc["lastname"] as? String
                        let email = doc["email"] as? String
                        let phoneNumber = doc["phone"] as? String

                        //  Do something with the property data retrieved.

                        print(firstName ?? "",
                              lastName ?? "",
                              email ?? "",
                              phoneNumber ?? "")
                    }
                }
            }
        }
    }