Создать упорядоченный индекс при асинхронном создании документа - PullRequest
0 голосов
/ 21 октября 2019

Я создаю систему комментариев с расширенными возможностями отложенной загрузки на клиенте, например, так:

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

Для этого мне нужно, чтобы мой документ comments был пронумерован (чтобы узнать, есть ли еще комментариизагружать между двумя комментариями) в соответствии с временем их создания.

Дело в том, что облачные функции запускаются асинхронно, для меня нет реального способа индексировать входящие документы на основе времени создания.

Например, один документ, созданный через несколько мс после другого, может раньше вызвать облачную функцию и, следовательно, вызвать ошибку в индексе.

Единственное решение, которое я могу придумать сейчас, - это для каждого входящего comment выполнитьзапрос числа comments в коллекции, которая имеет временную метку, меньшую этой, и использует ее в качестве индекса. Но это, очевидно, не совсем реально с точки зрения затрат / производительности.

Как бы вы подошли к этой проблеме? :)

Ответы [ 2 ]

0 голосов
/ 21 октября 2019

Благодаря предложению Дуга повернуть проблему назад и назначить индекс ДО присвоения метки времени в облачной функции, чтобы обеспечить порядок индекса, я придумал следующий код:


  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.`);
    }
  });

Itиспользует транзакцию для получения атомарного значения текущего количества уже сделанных комментариев, а затем использует это значение в качестве индекса комментария перед назначением соответствующей метки времени

0 голосов
/ 21 октября 2019

Назначьте метку времени создания комментария в самой функции, а не на клиенте. Тогда вы по-прежнему получаете заказ на основе времени, не требуя от клиента немедленной синхронизации записи документа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...