Search code examples
swiftfirebasedictionaryfirebase-realtime-databasesetvalue

Swift set a value of firebase dictionary with sub dictionaries


I have an object which has an sub object array in it. I want to save this object to firebase database as it is. How can I do this saving process in swift?

I tried creating new dictionaries

-LQTDo9OU9zw84IKnnW3
     code: "111"
     date: "4/11/2018"
     dateAndTime: "2018/11/4/12/18"
     description: "Description"
     editor: "Burak Akdeniz"
     predictions
          -0
            prediction: "Maç Sonucu 1"
            predictionRatio: "2"
    startTime: "12 : 18 PM"
    status: "Waiting"



let newMatchRef = refMatches.child("platinium").childByAutoId()
            let m : Dictionary<String, AnyObject> = [
            "code": match.code as AnyObject,
            "date": match.date as AnyObject,
            "dateAndTime": match.dateAndTime as AnyObject,
            "description": match.description as AnyObject,
            "editor": match.editor as AnyObject,
            "league": match.league as AnyObject,
            "matchType": match.matchType as AnyObject,
            "predictions": , //<--- HERE I have a predictions array includes prediction objects. This is the point I get error.
            "startTime": match.startTime as AnyObject,
            "status": match.status as AnyObject,
            "team1": match.team1 as AnyObject,
            "team2": match.team2 as AnyObject]
            print(newMatchRef)
            newMatchRef.setValue(m)

I need to save this object to firebase database with its sub nodes


Solution

  • The 'key' to Firebase is to always think of parent and child nodes as key: value pairs. Keys are always strings but values can be strings, numbers, bools and arrays.

    In this case, you've pretty much got it right, just need to consider the array to be a value in itself.

    Let's define that array with two elements (each element being a dictionary)

        let myArray = [
            ["prediction": "pred 0",
             "predictionRatio": "2"],
    
            ["preduction": "pred 1",
             "predictionRatio": "3"]
        ]
    

    then, let's create a dictionary object, which holds the key: value pairs and write the whole thing to firebase.

        let dict:[String: Any] = [
            "code": "1111",
            "date": "04/11/2018",
            "description": "Description",
            "predictions": myArray
        ]
    

    and then write it to a reference created with .childByAutoId

        let ref = self.ref.child("some_node").childByAutoId()
        ref.setValue(dict)
    

    and the results within some_node looks like this

    child_by_auto_id_0
       code: "1111"
       date: "04/11/2018"
       description: "some description"
       predictions:
          0:
             "prediction": "pred 0"
             "predictionRate": "2"
          1:
             "prediction": "pred 1"
             "predictionRate": "3"
    

    Note that I told the dictionary it's going to be getting key: value pairs of String: Any. The keys, as mentioned above, are always strings, but in this case some of the values are strings and then one is the array. The 'Any' type handles that.

    That being said, it's usually best to avoid arrays in Firebase. They are challenging to work with, not easily maintained and queries well... they just don't like to be queried. It would be better to generate the keys to the array using the same .childByAutoId method. It's far more flexible.

       predictions:
          auto_id_0:
             "prediction": "pred 0"
             "predictionRate": "2"
          auto_id_1:
             "prediction": "pred 1"
             "predictionRate": "3"
    

    On that note, you may want to consider denormalizing your predictions node if you will every want to query them

    child_by_auto_id_0
           code: "1111"
           date: "04/11/2018"
           description: "some description"
    
    predictions
          auto_id_0:
             "prediction": "pred 0"
             "predictionRate": "2"
             "parent_node_ref": "child_by_auto_id_0"
          auto_id_1:
             "prediction": "pred 1"
             "predictionRate": "3"
             "parent_node_ref": "child_by_auto_id_0"