Android Firestore查询分页FirebaseFirestoreException:无效的\u参数

Android Firestore查询分页FirebaseFirestoreException:无效的\u参数,android,firebase,kotlin,google-cloud-firestore,paging,Android,Firebase,Kotlin,Google Cloud Firestore,Paging,我有一个从firestore数据库获取帖子的函数,我正在跟踪文档,以便按最后一个索引文档对查询进行分页,但由于某种原因,在第一次获取后,当尝试运行下一个查询时,我收到com.google.firebase.firestore.FirebaseFirestoreException:无效的\u参数:Order by子句不能包含重复的字段上载时间戳 我还记录了日志,看到查询似乎正常,lastVisible在运行第一次查询后实际上是文档列表中的索引4,但不知何故,在第二次查询中,我又收到了所有前5篇帖子

我有一个从firestore数据库获取帖子的函数,我正在跟踪文档,以便按最后一个索引文档对查询进行分页,但由于某种原因,在第一次获取后,当尝试运行下一个查询时,我收到
com.google.firebase.firestore.FirebaseFirestoreException:无效的\u参数:Order by子句不能包含重复的字段上载时间戳

我还记录了日志,看到查询似乎正常,
lastVisible
在运行第一次查询后实际上是文档列表中的索引4,但不知何故,在第二次查询中,我又收到了所有前5篇帖子

知道我做错了什么吗


suspend fun getMyPosts(userID: String): Flow<MutableList<DocumentSnapshot>> = flow {
        Log.d(TAG, "getMyPosts() called -> userID is $userID")
        var data: QuerySnapshot? = null
        try {
            data = dbRef.collection("posts")
                .whereEqualTo("userID", userID)
                .orderBy("uploadTimeStamp", Query.Direction.DESCENDING)
                .limit(5)
                .get()
                .await()
            Log.d(TAG, "emitting ${data.documents.size} posts: \n")
            data.documents.forEach { doc ->
                Log.d(
                    TAG,
                    "post number ${data.documents.indexOf(doc)}, timestamp: ${doc.get("uploadTimeStamp")}"
                )
            }

            emit(data.documents)
            while (!data!!.isEmpty && data.size() == 5) {
                Log.d(TAG, "getting more posts")
                val lastVisible = data.documents[data.size() - 1]
                Log.d(TAG, "last index is ${data.size() - 1}")
                Log.d(TAG, "lastVisible is ${lastVisible.get("uploadTimeStamp")}")
                data = data.query
                    .whereEqualTo("userID", userID)
                    .orderBy("uploadTimeStamp", Query.Direction.DESCENDING)
                    .startAfter(lastVisible)
                    .limit(5)
                    .get()
                    .await()
                if (!data.isEmpty) {
                    Log.d(TAG, "emitting ${data.documents}")
                    emit(data.documents)
                }
            }
        } catch (e: Exception) {
            Log.d(TAG, "Failed to get MyPosts,\n $e")
            data!!.documents.forEach { doc ->
                Log.d(
                    TAG,
                    "post number ${data.documents.indexOf(doc)}, timestamp: ${doc.get("uploadTimeStamp")}"
                )
            }
        }
    }

这是我的firestore文档结构


如果我们稍微简化您的代码,您将执行以下操作:

var data: QuerySnapshot? = null
try {
    data = dbRef.collection("posts")
        .whereEqualTo("userID", userID)
        .orderBy("uploadTimeStamp", Query.Direction.DESCENDING)
        .limit(5)
        .get()
        .await()
    ...
    while (!data!!.isEmpty && data.size() == 5) {
        val lastVisible = data.documents[data.size() - 1]
        data = data.query
            .whereEqualTo("userID", userID)
            .orderBy("uploadTimeStamp", Query.Direction.DESCENDING)
            .startAfter(lastVisible)
            .limit(5)
            .get()
            .await()
因此,您通过再次调用
whereEqualTo
orderBy
来从原始值构建
数据,这就是错误消息所抱怨的

最简单的修复方法是不重复使用数据的现有值,从而将
data=data.query
更改为
data=dbRef.collection(“posts”)

但您似乎正在尝试构建器模式,这实际上是一种更好的方法。在这种情况下,您需要确保不重建整个查询,而只添加与分页部分相关的子句:

data = data.query
    .startAfter(lastVisible)
    .get()
    .await()

因此,这里我们只是添加了
startAfter
子句,因为所有其他条件都已经存在于
数据中。在您第一次构建它时查询它。

请编辑您的问题并将您的数据库结构添加为屏幕截图。感谢您为我标记它,这真的很有帮助!。事实上,我的循环查询保存了第一个查询中的
orderBy
WhereEqualTo
,因此指出它是重复的,所以现在一切正常。我确实希望执行另一个
data.query.startAfter(lastVisible)
会带来问题。顺便说一句,我通常会保留对“基本查询”的引用,即“除了
startAt
/
startAfter
”之外的所有内容,以便我可以将其用作分页的基础。
data = data.query
    .startAfter(lastVisible)
    .get()
    .await()