Mago Nicolas Palacios
Mago Nicolas Palacios

Reputation: 2591

Retrieving From Firebase Database with multiple childs

I have been working with Firebase for a while with no problem, but Recently I have a database structure with multiple childs, And Im having issues reading it on my code. Here is my Firebase Database Structure:

{
  "news" : {
    "50OzNLsK" : {
      "category" : "Anuncio",
      "content" : [ null, {
        "paragraph" : {
          "text" : "Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
        }
      }, {
        "quote" : {
          "image" : "http://www.magonicolas.cl",
          "quoteText" : "textoDelQuote"
        }
      } ],
      "date" : "Hoy",
      "imgURL" : "https://firebasestorage.googleapis.com/v0/b/rinnofeed.appspot.com/o/images%2Ftanta.jpg?alt=media&token=60f18a95-9919-4d81-ab1c-9976b71590fc",
      "likes" : 12,
      "summary" : "Este es el resumen de la noticia",
      "title" : "Mi NUeva noticia",
      "videoURL" : "https://youtu.be/S0YjUc7K3cw"
    }
  },
  "users" : {
    "tfeMODxXUnVvhvzntm77pKKtyfz2" : {
      "email" : "[email protected]",
      "store" : "Rinno"
    },
    "tpjn4feUuiTJmsd9lslHTREG1iE2" : {
      "email" : "[email protected]",
      "store" : "Rinno"
    }
  }
}

My problem is reading the internal information, for example the text in 500zNLsK/content/1/parahraph/text or the quote text in 500zNLsK/content/2/quote/quoteText

I have come this far:

DataService.ds.REF_NEWS.queryOrdered(byChild: "date").observe(.value, with: {(snapshot) in

            self.news = []


            if let snapshot = snapshot.children.allObjects as? [FIRDataSnapshot] {
                for snap in snapshot
                {
                    if let newsDict = snap.value as? Dictionary<String, AnyObject>
                    {
                        print("Mago Dict: \(newsDict)")

                        let key = snap.key
                        let new = News()
                        new.configureNews(newsKey: key, newsData: newsDict)
                        self.news.append(new)

                    }
                }
            }

And I can't make appear the inside content, it gives null. Help would me much appreciated :D

Upvotes: 0

Views: 1215

Answers (1)

Jay
Jay

Reputation: 35648

There are a number of changes you will need to make to your structure to have it work fluidly. Here's an example structure to get you going the right direction:

  "news"
    "topic_1"
      "category" : "topic 1 category"
      "content"
        "content_1"
          "paragraph"
            "text" : "topic 1 content 1 text"
        "content_2"
          "paragraph"
            "text" : "topic 1 content 2 text"
      "date" : "some date",
      "likes" : 12

    "topic_2"
      "category" : "topic 2 category",
      "content"
        "content_1"
          "paragraph"
            "text" : "topic 2 cotent 1 text"
        "content_2"
          "paragraph"
            "text" : "topic 2 content 2 text"
      "date" : "another date",
      "likes" : 425

Here's the commented code to get to the 'inside' most data

  newsRef.observe(.value, with: { snapshot in

    if ( snapshot!.value is NSNull ) {
        print("not found")
    } else {

        for child in (snapshot?.children)! {

            //snapshots are each node withing news: topic_1, topic_2
            let snap = child as! FDataSnapshot 

            //get each nodes data as a Dictionary
            let dict = snap.value as! [String: AnyObject] 

            //we can now access each key:value pair within the Dictionary
            let cat = dict["category"]
            print("category = \(cat!)")

            let likes = dict["likes"]
            print("  likes = \(likes!)")

            //the content node is a key: value pair with 'content' being the key and
            //  the value being a dictionary of other key: value pairs
            let contentDict = dict["content"] as! [String: AnyObject]

            //notice that the content_1 key: value pair has a key of content_1 
            //   and a value of yet another Dictionary
            let itemNum1Dict = contentDict["content_1"] as! [String: AnyObject]

            //new we need to get the value of content_1, which is
            //  'paragraph' and another key: value pair
            let paragraphDict = itemNum1Dict["paragraph"] as! [String: AnyObject]

            //almost there.. paragraphDict has a key: value pair of
            //   text: 'topic 1 content 1 text'
            let theText = paragraphDict["text"] as! String
            print("  text = \(theText)")

        }
    }
})

Some notes:

1) PLEASE don't user arrays in Firebase. They are evil and will cause you great grief. Your node names should be something describing the node (like 'news') and the child values created with childByAutoId. Even within the 'content' node I used content_1 and content_2 but those should also be created with childByAutoId

2) If you are iterating over nodes as in my example, the structure within the nodes should remain consistent. You can actually get around this a bit but for queries etc you are always better off being consistent.

3) Denormalizing is Normal. This structure works but you would gain some advantages making the entire structure shallower.

Upvotes: 2

Related Questions