FirebaseDatabase - 使用 UISearchController 时如何分页

FirebaseDatabase -How to Paginate when using a UISearchController

当用户在 searchBar 中键入文本时,UISearchController 有一个委托方法来更新搜索结果:

func updateSearchResults(for searchController: UISearchController) {

    guard let searchText = searchController.searchBar.text?.lowercased() else { return }

    Database...usersRef
        .queryOrdered(byChild: "username")
        .queryStarting(atValue: searchText)
        .queryEnding(atValue: searchText+"\u{f8ff}")
        .observe( .childAdded, with: { [weak self](snapshot) in

            let key = snapshot.key

            guard let dict = snapshot.value as? [String: Any] else { return }

            let user = User(userId: key, dict: dict)
            self?.datasource.append(user)
        })
}

效果很好。

当我通常分页时,我使用这个过程:

var startKey: String?

func handlePaginationForPosts() {

    if startKey == nil {

        Database...PostsRef
            .queryOrderedByKey()
            .queryLimited(toLast: 10)
            .observeSingleEvent(of: .value, with: { [weak self] (snapshot) in

                guard let children = snapshot.children.allObjects.first as? DataSnapshot else { return }

                if snapshot.childrenCount > 0 {
                    for child in snapshot.children.allObjects as! [DataSnapshot] {

                        let postId = child.key

                        if child.key != self?.startKey {

                            guard let dict = child.value as? [String:Any] else { return }

                            let post = Post(postId: postId, dict: dict)

                            self?.datasource.insert(post, at: 0)
                        }
                    }
                    self?.startKey = children.key
                }
            })

    } else {

        let lastIndex = datasource.count

        Database...PostsRef
            .queryOrderedByKey()
            .queryEnding(atValue: startKey!)
            .queryLimited(toLast: 11)
            .observeSingleEvent(of: .value, with: { [weak self] (snapshot) in

                guard let children = snapshot.children.allObjects.first as? DataSnapshot else { return }

                if snapshot.childrenCount > 0 {
                    for child in snapshot.children.allObjects as! [DataSnapshot] {

                        let postId = child.key

                        if child.key != self?.startKey {

                            guard let dict = child.value as? [String:Any] else { return }

                            let post = Post(postId: postId, dict: dict)
                            // I run a check to make sure the datasource doesn't contain the post before adding it
                            self?.datasource.insert(post, at: lastIndex)
                        }
                    }
                    self?.startKey = children.key
                }
            })
    }
}

这里的问题是 运行我使用的搜索:

.queryStarting(atValue: searchText)
.queryEnding(atValue: searchText+"\u{f8ff}")

但是在对 post 进行分页时,我使用:

.queryOrderedByKey()
.queryEnding(atValue: startKey!) ...

self?.datasource.insert(post, at: lastIndex)

startKeysnapshot.children.allObjects.first 中的第一个键,lastIndexdatasource.count

考虑到搜索查询是基于搜索文本而不是 key,当我已经使用 .queryEnding(atValue: searchText+"\u{f8ff}") 而不是 .queryEnding(atValue: startKey!) 时如何分页?

我需要跟踪从数据库中提取的键,以便在分页时我可以 运行 来自该特定键的下一组结果。

Firebase 数据库查询只能在单个 属性 上 order/filter。

因此,您可以 做的是过滤搜索条件,然后限制为前 N 个结果。

不能做的是过滤搜索条件,跳过前 N 个结果,然后获取下一页。

当您需要显示第 2 页时,您可以获得的最接近的结果是检索前 2*N 个结果,并且对于此类情况通常会做一些事情。但这会浪费一些带宽,因此您将不得不进行交易这与分页的有用性相悖。