如何检索按字段值排序的文档索引?

How to retireve a document index ranked by field value?

在我的 Android 测验应用程序中,我使用 Firebase Firestore 和 Pagination v3 Android Jetpack 库实现了排行榜,每个页面包含 2 个元素以降低阅读成本。我通过名为“分数”的字段的降序值查询文档。它适用于排行榜顶部的人。但是当用户例如第 1000 个时,如果不查询 1000 个文档我就无法显示它,因此它将花费 1000 次读取。那么有没有一种不用查询所有文档就能得到用户排名的方法呢?

编辑:

@HiltViewModel
class LeaderboardScreenViewModel @Inject constructor(

) : ViewModel() {

    private val db = Firebase.firestore
    
    val loadingState = MutableStateFlow(LoadingState.IDLE)

    val flow = Pager(PagingConfig(pageSize = 2)) {
        FirestorePagingSource(
            queryBestScores = db.collection("users_public_details").orderBy("score", Query.Direction.DESCENDING)
                .limit(6L)
        )
    }.flow
        .cachedIn(viewModelScope)

}


class FirestorePagingSource(
    private val queryBestScores: Query
) : PagingSource<QuerySnapshot, DocumentSnapshot>() {

    override fun getRefreshKey(state: PagingState<QuerySnapshot, DocumentSnapshot>): QuerySnapshot? =
        null

    override suspend fun load(params: LoadParams<QuerySnapshot>): LoadResult<QuerySnapshot, DocumentSnapshot> {
        return try {
            val currentPage = params.key ?: queryBestScores.get().await()
            val lastVisibleScore = currentPage.documents[currentPage.size() - 1]
            val nextPage = queryBestScores.startAfter(lastVisibleScore).get().await()
            LoadResult.Page(
                data = currentPage.documents,
                prevKey = null,
                nextKey = nextPage
            )
        } catch (e: Exception) {
            LoadResult.Error(e)
        }
    }


}

Is there a way to filter documents by a field value and get the 1000th of them without querying the previous 999 documents?

这实际上是不可能的。对于 Firestore,您只能使用 Query#limit(long limit) 方法请求特定大小的数据页面。话虽如此,您可以从查询的开头开始,并逐个获取相同大小的后续页面。此操作应继续执行其他类似操作,直到到达包含第 1000 个文档的页面。

您无法直接跳转到该文档。你总是必须阅读所有前面的页面。因此,您必须从第一页开始,然后使用 query cursors 向前浏览页面,方法是指定哪个文档是上一个查询中的最后一个文档。

除此之外,由于 Firestore 中的集合不维护文档计数,除非您创建和维护自己的文档计数,否则您将无法提前知道有多少页数据。

如果您想实现一种处理分页的现代方式,您应该考虑实现 so-called“无限滚动”。 Facebook 做到了这一点,Instagram 做到了这一点。那里有很多例子。

我也写过一篇文章叫:

我在其中解释了如何计算 Firestore 集合中的文档。