How can I auto-increment Firebase field names?

I’m currently working on an iOS application which outlines users to upload items they have into a Firestore database. Currently, my database has the following structure

  1. Users
    1.1 User1(unique user ID)
    1.1.2 firstname
    1.1.3 lastname
    1.1.4 products

When a user fills out the form and uploads the form data into the database, my code currently converts this into a String and uploads into the ‘products’ field. Here is my code:

if userId == user?.uid {
      let productDict =(productname,producturl,pricefield,proddesc,timeleft)
                            
         let combinedData = "\(productDict)"

      document.reference.updateData([
                              "products":(combinedData)
                            ])
                        }

However, if a user uploads another product by filling out the form again and uploading the data, then this will overwrite the data currently in ‘products’. I am aiming for my code to auto increment the ‘products’ field so that if the user uploaded another dataset then it would be put under ‘products2’, and then the next data upload would go under ‘products3’ etc. Here is the code I am currently using, how can I enable the auto-incrementing of the field names to match my example above (‘products’, ‘products2’, ‘products3’, ‘products4’) etc and for each upload to not overwrite previous ‘products’ data entries?

Not necessarily incrementing, but give the products a unique ID. And make it another nested object

So your structure would look more like:

1.1.4 products
1.1.4.1 product 1
1.1.4.2 product 2
Etc

1 Like

Hi, thanks for the response. I’ve updated my code by using the following to nest each of the product.

document.reference.updateData([
   "products.product1":(combinedData)
  ])

When a user uploads a product it is added to ‘product1’, however whenever they add another product, it keeps overwriting ‘product1’ instead of adding it as a new field called ‘product2’. I thought that it you use the ‘updateData’ method and there is already data in the “products.product1” field, then it will add the data into a new field?

I think you should be using setData

Update is for updating a single record. (I haven’t used Firestore though) you can lookup CRUD for Firestore and you’ll find it

Does this link help?

The link is very helpful thank you, I’ve got it working by posting product data into a separate collection. However now I am having issues re. reading the data because it is inside a series of different collections. My structure now works like this:

Users

  • User 1
    • Firstname
    • Lastname
    • email
      • ‘products’ collection
        • Product1
        • Product2

Currently, when I read the value in the ‘firstname’ column, I just use the following syntax:

    `let userFirstName = data["firstname"] as? String`

However I tried using the following, but it always returned ‘nil’.

   `let productName1 = data["products.product1"] as? String`

Can you post your actual collection data, in Firestore?

I think you’re referencing it wrong

Hi, here’s my actual collection data structure:

I’m trying to retrieve the “price” data value - which in the example is “£5.50”. I thought that potentially the following syntax could work to reference the ‘products’ collection?

let productName = document.reference.collection("products") = data["productname"] as? String

However when I use this syntax, I get the following error for the “collection” bit

Expression is not assignable: function call returns immutable value

I believe you can’t go directly to productName, I think you need something referencing “id” and then to productName

Does this link help?

I’ve just reviewed the Firestore documentation and it seems as though retrieving the IDs of sub collections cannot be done through conventional means.

So instead of this, when adding a new product to the database, I’m trying to loop through ‘product1’, ‘product2’ etc. to find the first one which == nil, and then post it there. Here is the function I am currently using to do this:

func incrementNumber() {
        db.collection("users").getDocuments { (snapshot, error) in
          if data["product"] as? String == nil {
          (products) = ["product"]
                return
                } else {
                try (products) += 1
                       }
                }
       }

This is my intended outcome, so that once a user adds their first product, it will be added as “product1”, however if they then add another product, then because “product1” is no longer = nil, then it will add it as 'product2".

However the code I am using returns the following error:

Invalid conversion from throwing function of type ‘(QuerySnapshot?, Error?) throws → Void’ to non-throwing function type ‘(QuerySnapshot?, Error?) → Void’

I managed to resolve this by using ‘ArrayUnion’ to add all product entries into a single array in Firestore and then read these separately.

2 Likes