user11182249
user11182249

Reputation:

queryStarting(atValue not working as intended?

I am wondering how I could use firebase ordering queries to make pagination work in my app.

So I have tried the following:

    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    if indexPath.row == postArray.count - 1 {
        //we are at last cell load more content
        //Do some logic here I think like
        limit += 10
         getRecentPosts(limit)
        //self.perform(#selector(reloadData), with: nil, afterDelay: 1.0)
    }
}

@objc func reloadData() {
    self.collectionView.reloadData()
}

And: I do this for it to work. But It does not, I expand on this below.

  ref.child("Timeline").child((Auth.auth().currentUser?.uid)!)
  .queryStarting(atValue: "\(postArray[postArray.count-1].user.userID!):\(postArray[postArray.count-1].media[0].postID!)")//here is a sample val: KVDB2sNMgUN90tpkmQKfjrroOmt1:post:580367065
  .queryLimited(toLast: UInt(limit)).observeSingleEvent(of: .value, with: { (snapshot) in

My fetch fucntion looks like this:

        } else {
        print("ffdsafsfsdfasdfsd?????", postArray.count)
        print("\(postArray[postArray.count-1].user.userID!):\(postArray[postArray.count-1].media[0].postID!)", "  fhdskagfakshgfjdshflkahflkjashlkjfhslkj")

        ref.child("Timeline").child((Auth.auth().currentUser?.uid)!)
            .queryStarting(atValue: "\(postArray[postArray.count-1].user.userID!):\(postArray[postArray.count-1].media[0].postID!)")
            .queryLimited(toLast: UInt(limit)).observeSingleEvent(of: .value, with: { (snapshot) in
                print("resulst here?????????")
                if let snapshots = snapshot.children.allObjects as? [DataSnapshot] {
                    print(snapshots, " this is the snapshot of the people you follow", snapshots.count)

                    for child in snapshots.reversed() {

                        let keyValue = child.key
                        let uid = keyValue.split(separator: ":")[0]
                        let postIDDoubleVal = keyValue.split(separator: ":")[2]


                        self.fetchUsersPost(uid: String(uid), postID: "post:\(postIDDoubleVal)")
                    }
                }
            })
    }
}

Update:

I have found that the logic works as needed but that inside the place where i print :

                    if let snapshots = snapshot.children.allObjects as? [DataSnapshot] {
                    print(snapshots, " this is the snapshot of the people you follow", snapshots.count)

I get the following output:

[]  this is the snapshot of the people you follow 0

Why is this? i checked the DB for the starting point I gave it and it does exist

Upvotes: 0

Views: 148

Answers (1)

Jay
Jay

Reputation: 35677

I don't fully understand the query in the question so let's see if we can produce an answer via an example.

Let's take a structure of posts

Timeline
   uid_0
      post_0: "a"
      post_1: "b"
      post_2: "c"
      post_3: "d"
      post_4: "e"
      post_5: "f"
      post_6: "g"
      post_7: "h"
      post_8: "i"
      post_9: "j"

There are multiple ways this can be paginated but let's use two simple examples.

In this first example, suppose we want three posts starting at post_3, so we want d, e and f, and we know the actual key to start with, post_3.

func paginationByKey() {
    let ref = self.ref.child("Timeline").child("uid_0")
    let q0 = ref.queryOrderedByKey() //they will be ordered by key
    let q1 = q0.queryStarting(atValue: "post_3").queryLimited(toFirst: 3)
    q1.observeSingleEvent(of: .value, with: { snapshot in
        print(snapshot)
    })
}

this will return

Snap (uid_0) {
    "post_3" = d;
    "post_4" = e;
    "post_5" = f;
}

In this second example, in many cases the node keys are generated with a push() or .childByAutoId so you won't know the key. However, you would know the starting value, like a date or timestamp for example. Also, the data could really be stored in any order in the database. To handle that we know the first value we want to read in is 'd' followed by 'e' and 'f'

func paginationByValue() {
    let ref = self.ref.child("Timeline").child("uid_0")
    let q0 = ref.queryOrderedByValue() //ordering the data by child value
    let q1 = q0.queryStarting(atValue: "d").queryLimited(toFirst: 3)
    q1.observeSingleEvent(of: .value, with: { snapshot in
        print(snapshot)
    })
}

and the output is

Snap (uid_0) {
    "post_3" = d;
    "post_4" = e;
    "post_5" = f;
}

To paginate, since you know the last node loaded had a value of 'f', the next set of data would start with 'g'. There are a couple of ways to handle that:

One way is to actually load in 4 nodes and display 3. The 4th node is the starting point for the next set of data, so you would perhaps keep that in a class var for reference.

Another option is to start the query at the last node of the set of nodes just loaded, 'f' in this case' but throw out the first one (which will be 'f') of the new set as it was already in the prior set.

Upvotes: 1

Related Questions