Eric Walters
Eric Walters

Reputation: 311

Counting Records In Swift From Firebase With A Where Statement

I am trying to return the count of posts for a specific user where a field contains a certain value. The structure I am using in Firebase is here:

{
  "posts" : {
    "-Lyzpsb1hH4LUPvcXE3H" : {
      "beverageCategory" : "Beer",
      "beverageName" : "Dortmunder",
      "beveragePrice" : "3.99",
      "beverageRating" : 3,
      "beverageType" : "Lager",
      "imageUrl" : "https://firebasestorage.googleapis.com/v0/b/socialspirit-37cae.appspot.com/o/post-pics%2F3C23E923-A3BD-4393-B3EF-8F939D8B08B8?alt=media&token=ac80cb98-f2a1-4197-b328-2a69a2ac1fd1",
      "wineVintage" : ""
    }
  },
  "user" : "sdkjvksdjf",
  "users" : {
    "0hyN8N2klJWqPi2lkRqNK3vg7z63" : {
      "posts" : {
        "-Ly6ciYHm7v5JFy1VmVY" : true,
        "-Ly6cyLukI6aRRki5yna" : true
      },
      "provider" : "Firebase"
    },
    "26OUuaRZEVWUmkLJp13LzirGbs13" : {
      "posts" : {
        "-Ly6fGmQEMZz3c-azMnJ" : true
      },
      "provider" : "Firebase"
    },
    "5r6FulsvIRap7pLK5D3zV8qyPVv1" : {
      "provider" : "Firebase"
    },
    "gQpktBMh97hTqiysHBwvVLZl70y1" : {
      "posts" : {
        "-Lyzpsb1hH4LUPvcXE3H" : true,
        "-LyzqFgvmrBgdsgKSt_5" : true,
        "-Lz-fIMDal00ex3_viQo" : true,
        "-Lz-lXsSBqKlcf8hBext" : true,
        "-Lz2eNLfk1PFEVkEgmwa" : true,
        "-Lz2etF0UqFqLkdGOR13" : true,
        "-Lz2fGUi0qzJtniNr5LX" : true,
        "-Lz2gP5c47yHDO2g0ljr" : true,
        "-Lz2gdhfedZfTtzjP2ee" : true,
        "-Lz2gllC3caXgPf2VAPU" : true,
        "-Lz2hH8FbNmBEOLcHCJz" : true,
        "-Lz2jzkXuEZ3Cfe96eGW" : true,
        "-Lz3RvuW4fMXarhW7vLv" : true,
        "-Lz3S8YA0vgk4ZrjL_Kk" : true
      },
      "provider" : "Firebase"
    }
  }
}

I am using the following code to get the count of records that have a beverageCategory of "Beer".

DataService.ds.REF_USERS.child("\(uid)").child("posts").child("beverageCategory")
.queryOrderedByValue().queryEqual(toValue: "Beer")
.observe(DataEventType.value, with: { (snapshot)     in
    print("SNAP - \(snapshot.childrenCount)")
})

The childrenCount returns 0, however. Any idea what I'm doing wrong here? Thanks!

EDIT: I added the JSON for the data structure and I think I left an important detail out. The data structure actually has users that have posts and the associated postid that links back to posts. I think what I have to do is first find the user's posts and then of those posts get a total count for each category. I'm guessing that is slightly different than the methods I tried. Any ideas on that?

EDIT 2: So my issues is that users and posts are in different structures. I need to find all of the user's posts and iterate through them to see if what the beverageCategory is. I have done that with the following code. The issue with the code below is that the count is doubled when I add a post and then open the menu. But when I exit the menu and re-open the count is correct. Why is it double-counting?

func myFirebaseNetworkDataRequest(finished: @escaping () -> Void) { 
    beerCountArray.removeAll()
    wineCountArray.removeAll()
    liquorCountArray.removeAll()

    print("BEER ARRAY \(beerCountArray.count)")

    guard let uid = Auth.auth().currentUser?.uid else {
        return
    }
    let newPost = DataService.ds.REF_USERS.child("\(uid)").child("posts")

    newPost.observe(.value, with: { (snapshot) in
         if let snapshot = snapshot.children.allObjects as? [DataSnapshot] {
             //print("SNAPSHOT - \(snapshot)")
             for snap in snapshot {
                 let postData = DataService.ds.REF_POSTS.child(snap.key)
                 //print("SNAP KEY - \(snap.key)")
                 let bevCat = DataService.ds.REF_POSTS.child(snap.key).child("beverageCategory")
                 //print("BEV CAT - \(bevCat)")
                 postData.observe(.value, with: { (snapshot) in
                     if let postDict = snapshot.value as? Dictionary<String, AnyObject> {
                         let key = snapshot.key
                         let post = Post(postKey: key, postData: postDict)
                         //print("POST DICT - \(String(describing: postDict["beverageCategory"]!))")
                        if postDict["beverageCategory"]! as! String == "Beer" {
                            self.beerCountArray.append(1)
                            //print("BEER ARRAY LOOP - \(self.beerCountArray)")
                         }
                        if postDict["beverageCategory"]! as! String == "Wine"{
                            self.wineCountArray.append(1)
                         }
                        if postDict["beverageCategory"]! as! String == "Liquor" {
                            self.liquorCountArray.append(1)
                        }
                         //self.posts.append(post)
                     }
                     finished()
                 })
             }
         }

     })

}

And...

 override func viewDidLoad() {
        super.viewDidLoad()

        beerCountArray.removeAll()
        wineCountArray.removeAll()
        liquorCountArray.removeAll()

        myFirebaseNetworkDataRequest {

            //print("BEER ARRAY - \(self.beerCountArray.count)")
            self.beerCount.text = String(self.beerCountArray.count)
            self.liquorCount.text = String(self.liquorCountArray.count)
            self.wineCount.text = String(self.wineCountArray.count)
        }
}

Upvotes: 0

Views: 213

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 598797

Your query is not correct. Since you're trying to filter on a child property of each node under posts, you should call queryOrdered(byChild:).

So:

DataService.ds.REF_USERS.child("posts")
  .queryOrdered(byChild: "beverageCategory")
  .queryEqual(toValue: "Beer")
  .observe(DataEventType.value, with: { (snapshot)     in
    print("SNAP - \(snapshot.childrenCount)")
  })

Also see the Firebase documentation on ordering and filtering data.

Upvotes: 1

Related Questions