Firebase subcollections


I need the users to have one id as basic data and contact info but for several users


I did for my project and was rejected pls whats collection group query and how can it be used

Thinking about this a little more I am wondering what the point is by having a collection within a collection. It makes the process so complicated when you only have data about the user that can be stored in a single level collection.

You are only saving details about the user such as:

dateofbirth
email
id
name
phonenumber
username
time

…so there seems little point in having a collection “basic-data” within the “user” collection.

You are better off just having a single collection where each document is for each user and the documentID is the uid of the currentUser when they log in. The uid for the user never changes. When you use authentication by, say, email and password and create the user if they don’t exist, that uid remains with that user.

Do you see what I am getting at?

i see that but this is like a stage 2 assessment for a company i am applying for so it has one user fetch under that users we have other users (usera,userb,userc)which have the same (id basicdata)then id (contact info) after then name time and timestamp…i can easily create that on firebase but how would i fetch and post there

db.collections(users) then what next because they have diff id of user but same id for basic data and contact info?

Do you have a document that describes the assessment process and what you need to do? I can’t see the point of having a collection which has no data itself and a sub-collection that has the users basic-data.

Remember earlier when I was talking about the user logging in? When each user is created on Firebase in the Authentication process, they are allocated a unique UID. In your Firestore database you can use that unique UID as the documentID for each users details like this screenshot:

You would have multiple documents under “user” and all of them would be for different users in which their details are stored.

Does that make sense?

Wow, very strange assessment. Rather unfair in my opinion but that’s how it is.

I was able to successfully create, retrieve, update and delete a record to suit that structure.

Note that in each case I used a 20 character random string that serves as a UID (or userId as I named it in the code).

I also created these two functions to create a timestamp that is in milliseconds and convert a timestamp from milliseconds to a Date.

    func currentTimeInMilliSeconds() -> String {
        let currentDate = Date()
        let since1970 = currentDate.timeIntervalSince1970
        return String(Int(since1970 * 1000))
    }

    func dateFromMilliseconds(timestamp: String) -> Date {
        let timeInterval = TimeInterval(Int(timestamp)! / 1000)
        return Date(timeIntervalSince1970: timeInterval)
    }

Create code

    func createUserDetails() {

        let userId = "u4tk50rkkylxuz9iycwo"

        let dob = "01/01/2000"
        let name = "Ben Dover"
        let email = "ben@somedomain.com"
        let phoneNumber = "01234567890"
        let username = "bendyman"

        let db = Firestore.firestore()

        let userCollection = db.collection("user")

        // Create the initial user record with a field named "date"
        userCollection.document(userId)
            .collection("basic_data")
            .document("contactinfo")
            .setData(["dob": dob,
                      "email": email,
                      "name": name,
                      "phonenumber": phoneNumber,
                      "timestamp": currentTimeInMilliSeconds(),
                      "username": username])
    }

Retrieve code:

    func getUserDetails() {
        // Get the current userId which will correspond to the user document id
        let userId = "u4tk50rkkylxuz9iycwo" //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")
            .document("contactinfo")

        // initiate the fetch. NOTE getDocument is singular ie. One document.
        user.getDocument { document, error in
            // Check for errors
            if let error = error {
                print(error.localizedDescription)
            } else {
                if let doc = document {
                    // We have data retrieved so process it.
                    let dob = doc["dob"] as? String
                    let email = doc["email"] as? String
                    let name = doc["name"] as? String
                    let phoneNumber = doc["phonenumber"] as? String
                    let timestamp = doc["timestamp"] as? String
                    let username = doc["username"] as? String

                    //  Do something with the property data retrieved.

                    print(dob ?? "",
                          email ?? "",
                          name ?? "",
                          phoneNumber ?? "",
                          dateFromMilliseconds(timestamp: timestamp ?? "0"),
                          username ?? "")

                }
            }
        }
    }

Update Code:

    func updateUserDetails() {

        let userId = "u4tk50rkkylxuz9iycwo"
        let newPhone = "0981234567"

        let db = Firestore.firestore()

        let userCollection = db.collection("user")
            .document(userId)
            .collection("basic_data")
            .document("contactinfo")

        userCollection.updateData(["phonenumber" : newPhone])
    }

Delete Record code
The delete process is rather tricky and my guess is that the people who set this task knew that it would be and probably thought it would catch some people out.

It’s a three step process since you can’t just delete the record at the root documentID because there is nested data that must be removed first.

So the process is to

  • Detete the contactinfo first
  • Then add a dummy record to the root document since you can’t delete it without some data at the root document level. I have no idea why but I guess Firebase did this for a good reason.
  • Then delete the root document.
    func deleteUserDetail() {
        let userId = "u4tk50rkkylxuz9iycwo"

        let db = Firestore.firestore()

        let userCollection = db.collection("user")
            .document(userId)
            .collection("basic_data")
            .document("contactinfo")

        //  First delete the contactinfo details
        userCollection.delete { error in
            if let error = error {
                print(error.localizedDescription)
            } else {
                // Now add dummy record to root document otherwise you cannot delete it
                db.collection("user").document(userId).setData(["dummy": "dummy"], merge: true) { error in
                    if let error = error {
                        print(error.localizedDescription)
                    } else {
                        // Now delete the user record
                        db.collection("user").document(userId).delete { error in
                            if let error = error {
                                print(error.localizedDescription)
                            } else {
                                print("User record deleted entirely")
                            }
                        }
                    }
                }
            }
        }
    }

See how you go with that in your project.

the get logged user id I am talking about sorry so I can fetch several for the list

@jermaine4

I assume you are talking about this function that retrieves the currently logged in user’s uid:

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

In each of the create, retrieve, update and delete functions, where you see

let userId = "u4tk50rkkylxuz9iycwo"

use

let userId = getLoggedInUser()

sorry chris the userid is not working when I use the id mentioned for user it works but the getlogged() id does it connect with the userid automatically for each user? wh

@jermaine4

Are you actually going through a login or create user phase in your App?

im not going through any login screen

@jermaine4

If you are not actually logging in through Firebase then there is no way to automatically retrieve a “uid” from Firebase. Firebase provides an Authentication module that you can configure. You need associated code in your App to either login an existing user or to enable a new user to create a login.

When the user logs in, that uid can be retrieved and used in other parts of Firebase such as the Firestore module (which the same code I have provided relates to) and/or the Storage module.

Everything I am showing you with the code I have supplied is done using a manually generated uid to “simulate” what would happen IF you had set up Firebase Authentication.

It will also work IF you have Authentication in place by using that function getLoggedInUser() since that returns the currently logged in users’ uid.

I hope that clears up any misunderstanding.


so I didit like this so how can I fetch it back now

putting the solution here well I finally did it using group collection fetch and using uuid to pass to firebase and using generated id to fetch it sadly after my efforts the company didn’t take me but we remain hopeful