在异步文档创建时创建有序索引

时间:2019-10-21 12:27:34

标签: google-cloud-firestore google-cloud-functions

我正在像这样在客户端上构建具有高级延迟加载功能的评论系统:

comment 1
 |
[load more]
 | 
comment 7
 |
comment 8
 |
[load more]
 |
comment 10

为此,我需要根据创建时间对comments文档进行编号(以了解两个注释之间是否还有更多注释要加载)。

事实是,由于云函数触发器是异步的,因此我没有真正的方法根据创建时间来索引传入的文档。

例如,一个文档在几毫秒后创建,可能会更早触发云功能,从而导致索引错误。

我现在唯一想到的解决方案是,对于每个传入的comment,对集合中时间戳次于comments的{​​{1}}数量进行查询,并将其用作指数。但这显然在成本/性能方面并不可行。

您将如何解决这个问题? :)

2 个答案:

答案 0 :(得分:0)

在函数本身中而不是在客户端上分配注释的创建时间戳。然后,您仍然可以基于时间进行订购,而不必要求客户端立即同步文档写入。

答案 1 :(得分:0)

感谢道格的建议,将问题向后转并在为云功能分配时间戳之前分配索引,以确保索引顺序,我想到了以下代码:


  const { post_id, text } = data;

  return db.runTransaction(async transaction => {
    const postDocRef = db.collection('posts').doc(post_id);
    const postComDocRef = postDocRef.collection('comments').doc();

    const postDoc = await transaction.get(postDocRef);
    if (!postDoc.exists)
      throw new functions.https.HttpsError(
        'not-found',
        `Post ${post_id} not found.`
      );
    try {
      const comments_count = postDoc.data()!.comments_count;
      transaction.update(postDocRef, {
        comments_count: comments_count + 1
      });
      transaction.create(postComDocRef, {
        author: context.auth!.uid,
        text,
        index: comments_count,
        created_at: admin.firestore.Timestamp.now()
      });
    } catch (e) {
      throw new functions.https.HttpsError('internal', `Transaction failed.`);
    }
  });

它使用事务获取当前已经进行的注释计数的原子值,然后在分配相应的时间戳之前将该值用作注释索引