How to split request on firebase that contains equalTo () api
I am coding a shopping site with firebase. I have some categories and subcategories in the sidebar that onClick them, the feed posts need to be updated accordingly, ordered by time and just show posts from the selected category.
place object in firebase database:
-KiKGQUZ4XaZPHxvOZD-addclose {
categorie:0
subCat: 2
....
}
There are many posts out there and I need to paginate them
To do this, I have to query like this:
dbRef
.orderByChild('categories')
.equalTo(category)
.limitToLast(QUERY.PAGINATION_COUNT)
.on('value', (snapshot) => {
cb(_toArray(snapshot).reverse());
});
But I cannot paginate with equalTo ().
I think the solution should be:
dbRef
.orderByChild('categories')
.equalTo(category)
.startAt(lastFetchedItem.fbKey)
.limitToLast(QUERY.PAGINATION_COUNT)
.on('value', (snapshot) => {
cb(_toArray(snapshot).reverse());
});
But it is not possible to firebase fulfilled the request equalTo
and startAt
at the same time
How can I solve this problem?
source to share
I ended up changing the realtime firebase database schema.
I'm not sure, but I think firebase intentionally doesn't release more apis. This forces you to double check your circuit and improve it.
I created a dedicated collection for categories and in a category collection created with a separate node for each category. Its firebase recommends to structure your database.
Then put each new post in the appropriate category.
So I can easily use OrderByKey()
in each category and subcategories and paginate them using startAt
or endAt
apis
Another solution would be to use the firebase and elastic search function. For this purpose, a FlashLight package has been created .
source to share
Based on this source, it looks like this functionality is not possible and is not going to be added. You can do something like this though
- Request the initial paging amount using equalTo
- Query by key ending with your last visible key and filter the results if the category matches the one you want, then add, otherwise ignore it.
I wrote my code in Swift3 but had the same problem, maybe my code will be useful to others.
static func filterTableByCategory(tableNumber: String, category: String) {
filteringRef.child(tableNumber).queryOrdered(byChild: "category").queryEqual(toValue: category).queryLimited(toLast: 9).observeSingleEvent(of: .value, with: { snap in
if snap.exists() {
currentTablePosts.removeAll()
for child in snap.children {
let child = child as? DataSnapshot
if let post = child?.value as? [String: AnyObject] {
let posst = Post()
if let author = post["author"] as? String, let likes = post["likes"] as? Int, let pathToImage = post["pathToImage"] as? String, let postID = post["postID"] as? String, let postDescription = post["postDescription"] as? String, let timestamp = post["timestamp"] as? Double, let category = post["category"] as? String, let table = post["group"] as? String, let userID = post["userID"] as? String, let numberOfComments = post["numberOfComments"] as? Int, let region = post["region"] as? String {
posst.author = author
posst.likes = likes
posst.pathToImage = pathToImage
posst.postID = postID
posst.userID = userID
posst.fancyPostDescription = Helper.createAttributedString(author: author, postText: postDescription)
posst.postDescription = author + ": " + postDescription
posst.timestamp = timestamp
posst.table = table
posst.region = region
posst.category = category
posst.numberOfComments = numberOfComments
posst.userWhoPostedLabel = Helper.createAttributedPostLabel(username: author, table: table, region: region, category: category)
if let people = post["peopleWhoLike"] as? [String: AnyObject] {
for(_, person) in people {
posst.peopleWhoLike.append(person as! String)
}
}
currentTablePosts.insert(posst, at: 0)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTableCollectionView"), object: nil)
} // end of if let
}
}
}
else {
currentTablePosts.removeAll()
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTableCollectionView"), object: nil)
}
})
filteringRef.removeAllObservers()
}
static func getMoreFilterByCategoryPosts(tableNumber: String, category: String, lastVisibleKey: String) {
pagingReference.child(tableNumber).queryOrderedByKey().queryEnding(atValue: lastVisibleKey).queryLimited(toLast: 12).observeSingleEvent(of: .value, with: { snap in
if snap.exists() {
let currentNumberOfPosts = currentTablePosts.count
for child in snap.children {
let child = child as? DataSnapshot
if let post = child?.value as? [String: AnyObject] {
if let cat = post["category"] as? String, let postID = post["postID"] as? String {
if cat == category && postID != lastVisibleKey {
let posst = Post()
if let author = post["author"] as? String, let likes = post["likes"] as? Int, let pathToImage = post["pathToImage"] as? String, let postDescription = post["postDescription"] as? String, let timestamp = post["timestamp"] as? Double, let table = post["group"] as? String, let userID = post["userID"] as? String, let numberOfComments = post["numberOfComments"] as? Int, let region = post["region"] as? String {
posst.author = author
posst.likes = likes
posst.pathToImage = pathToImage
posst.postID = postID
posst.userID = userID
posst.fancyPostDescription = Helper.createAttributedString(author: author, postText: postDescription)
posst.postDescription = author + ": " + postDescription
posst.timestamp = timestamp
posst.table = table
posst.region = region
posst.category = cat
posst.numberOfComments = numberOfComments
posst.userWhoPostedLabel = Helper.createAttributedPostLabel(username: author, table: table, region: region, category: category)
if let people = post["peopleWhoLike"] as? [String: AnyObject] {
for(_, person) in people {
posst.peopleWhoLike.append(person as! String)
}
}
currentTablePosts.insert(posst, at: currentNumberOfPosts)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTableCollectionView"), object: nil)
} // end of if let
}
}
}
}
}
else {
print("snap == nil")
}
})
pagingReference.removeAllObservers()
}
source to share