Converting maps from Firestore to dictionary in Swift

Viewed 1912

I am creating a order system, and for that, I am storing the cart of a user in Firestore with maps, so the collection will be called "carts", then the document will be saved as the user's UID and inside of the document there should be maps with what he ordered, the quantity and the price of those things, so for example he orders 4 things and for that there are 4 maps in which there are the item names, the quantity and the price stored.

Now I don't know how I can retrieve this data from Firebase within Swift and save it in a dictionary. For other data types I always used a SnapshotListener, but I really have no idea how that would work for data in maps that I want to save in dictionaries.

Edit: My firebase structure would be like this and I want to save this data (item name, quantity, price) in one dictionary in Swift, so that I can pass on this information as one.

My database structure in Firestore

Edit 2:

class readDrinksFromDb: ObservableObject {
@Published var items = [Item]()
@ObservedObject var userInfo = UserData()

init () {
    let db = Firestore.firestore()
    let itemsRef = db.collection("drinks")
    let loungeRef = itemsRef.document(userInfo.user.reserviert) // Should get the lounge Name -> XYZ Lounge

    loungeRef.getDocument { (snap, err) in
        if let err = err {
            print(err.localizedDescription)
            return
        }

        guard let snap = snap else { return }
        guard let dict = snap.data() else { return }

        dict.forEach { i in
            let orderItems = dict[i.key] as! [String: String]
            let id = orderItems["id"] ?? ""
            let price = orderItems["price"] ?? ""
            let pic = orderItems["pic"] ?? ""
            let name = orderItems["name"] ?? ""

            self.items.append(Item(id: id, name: name, price: price, pic: pic, lounge: "Rebell Lounge", type: "drinks"))
        }

        print(self.items)
    }

}

}

1 Answers

I may not fully understand the question but I think you're asking how to read data from a document in Firestore and access the child data.

I'm including two examples, one using dictionaries to get to the data and the second using .map. Read through the first part first as it best illustrates the relationships between the data

Dictionaries:

If so, assuming the users uid is 'user_0', we'll read the topmost document has the users uid as the documentId.

Once we have the document, we use the .data property to get all of the data as a Dictionary.

guard let dict = snap.data() else { return }

Then, the field (a dictionary key) we are interested in is called 'drinks' so we use the 'drinks' key to get it's value (which is another dictionary)

let orderItems = dict["drinks"] as! [String: String]

The overall structure looks like this

["drinks": {
    item = fanta;
    price = "4.50";
    quantity = 2;
}]

As you can see drinks is the key and then the item, price and quantity are the value associated with that key

Then, those items are cast to a orderItems variable

let orderItems = dict["drinks"] as! [String: String]

which is also a dictionary and contains the keys and values of the data you want

func readOrder() {
    let orderRef = self.db.collection("orders") //self.db = my Firestore
    let thisUser = orderRef.document("user_0")

    thisUser.getDocument(completion: { snapshot, error in
        if let err = error {
            print(err.localizedDescription)
            return
        }

        guard let snap = snapshot else { return }

        guard let dict = snap.data() else { return }

        let orderItems = dict["drinks"] as! [String: String]

        let item = orderItems["item"] ?? "No Item"
        let price = orderItems["price"] ?? "No Price"
        let qty = orderItems["quantity"] ?? "No Quantity"
        print(item, price, qty)
    })
}

Using .map

func readOrder() {
    let orderRef = self.db.collection("orders")
    let thisUser = orderRef.document("user_0")

    thisUser.getDocument(completion: { snapshot, error in
        if let err = error {
            print(err.localizedDescription)
            return
        }

        let mappedField = snapshot.map {$0}
        let orderDict = mappedField?.get("drinks") as! [String: String]
        let item = orderDict["item"] ?? "No Item"
        let created = orderDict["price"] ?? "No Price"
        let age = orderDict["quantity"] ?? "No qty"
        print(item, created, age)
    })
}

Edit

Responding to a comment about how to iterate over a dictionary to get it's key: value pairs. Here's two options

for (key, value) in dict {
    print(key, value)
}

dict.forEach { key, value in
    print(key, value)
}
Related