【问题标题】:How would I paginate Firestore data with cloud functions?如何使用云功能对 Firestore 数据进行分页?
【发布时间】:2020-09-03 02:22:12
【问题描述】:

我正在尝试对数据进行分页,以便可以无限滚动查看我的应用上的帖子。我有一个名为 getPosts 的云函数,其中有多个读取函数。一切正常。但是当我尝试使用云函数考虑分页时,我遇到了将最后一个快照作为查询参数发送的问题。此快照将超长且出乎意料的长度,超过 3000 个字符。这是我的 getPosts 函数:

exports.getPosts = (req, res) => {
    const postId = req.query.postId;

    if(postId != null){
        db
            .collection('posts')
            .doc(postId)
            .get()
            .then((doc) => {
                if(!doc.exists){
                    throw 'postNotFound';
                }
                else{
                    const voteCount = sumValues(doc.data().votingOptions);
                    let liked;
                    let votingOptionsDictionary;
                    return db.collection('votes')
                        .where('postId', '==', doc.id)
                        .where('userHandle', '==', req.user.userHandle)
                        .get()
                        .then((voteDoc) => {
                            return db.collection('likes')
                                    .where('postId', '==', doc.id)
                                    .where('userHandle', '==', req.user.userHandle)
                                    .get()
                                    .then((likeDoc) => {
                                        liked = likeDoc.empty ? false : true;
                                        return res.json([{
                                            postId: doc.id,
                                            userHandle: doc.data().userHandle,
                                            postQuestion: doc.data().postQuestion,
                                            userImageUrl: doc.data().userImageUrl,
                                            imageUrl: doc.data().imageUrl,
                                            postDescription: doc.data().postDescription,
                                            createdAt: doc.data().createdAt
                                        }]);
                                    });
                        });
                }
            })
            .catch((err) => {
                if(err == "postNotFound"){
                    return res.json({'Error': `Post ID ${postId} does not exists`});
                }
                else{
                    console.error(err);
                    return res.json({error: err});
                }
            });
    }
    else{
        db
            .collection('posts')
            .orderBy('createdAt', 'desc')
            .limit(10)
            .get()
            .then(async (data) => {
                const promises = await data.docs.map((doc) => {
                    const voteCount = sumValues(doc.data().votingOptions);
                    let liked;
                    let votingOptionsDictionary;
                    return db.collection('votes')
                        .where('postId', '==', doc.id)
                        .where('userHandle', '==', req.user.userHandle)
                        .get()
                        .then((voteDoc) => {
                            return db.collection('likes')
                                    .where('postId', '==', doc.id)
                                    .where('userHandle', '==', req.user.userHandle)
                                    .get()
                                    .then((likeDoc) => {
                                        liked = likeDoc.empty ? false : true;
                                        return {
                                            postId: doc.id,
                                            userHandle: doc.data().userHandle,
                                            postQuestion: doc.data().postQuestion,
                                            userImageUrl: doc.data().userImageUrl,
                                            imageUrl: doc.data().imageUrl,
                                            postDescription: doc.data().postDescription,
                                            createdAt: doc.data().createdAt
                                        };
                                    });
                        });
                })
                Promise.all(promises)
                    .then((posts) => {
                        res.json(posts);
                    })
            })
            .catch((err) => {
                console.error(err);
                res.status(500).json({ error: err.code});
            });
    }
}

我正在考虑将快照对象保存在客户端,然后将其作为可选查询参数发送到 getPosts 云函数以获取我想要的数据,但我几乎可以肯定我无法将该对象发送为一个查询参数...

【问题讨论】:

    标签: node.js google-cloud-firestore pagination google-cloud-functions


    【解决方案1】:

    如果您不能使用实际的 DocumentSnapshot 对象作为分页的锚文档,您可以简单地使用文档中与排序顺序相关的字段值。这在documentation 中有描述。因此,如果您在 createdAt 上有单个排序,可以将相关字段值传递给 startAt()startAfter()

    如果您根本没有定义顺序,则排序顺序基于文档 ID,您可以简单地使用 where 子句来获取大于或小于您指定 ID 的所有文档。例如:where(FieldPath.documentId(), ">", id)

    【讨论】:

    • 完美运行。谢谢!
    • 嘿,又遇到了一个问题。我有一个带有 threadCommentCount 的 orderBy 字段的 cmets 查询。许多 cmets 的 threadCommentCount 为 0,因此每次我将最后一条评论 threadCommentCount 传递到 startAfter 值为 0 的另一个查询中时,它每次都返回相同的数据集。我将如何解决这个问题?我可以在第一个之后添加另一个 startAfter 或 orderBy 吗?
    • 如果您有新问题,请单独发布。
    猜你喜欢
    • 1970-01-01
    • 2019-04-02
    • 1970-01-01
    • 2020-08-02
    • 1970-01-01
    • 2018-06-30
    • 2018-04-23
    • 1970-01-01
    • 2018-11-17
    相关资源
    最近更新 更多