Использование облачной функции Firebase для копирования всех документов из основной коллекции в Firestore в новую вложенную коллекцию - PullRequest
0 голосов
/ 07 февраля 2020

У меня есть основная коллекция в firestore с парой сотен документов (которые вырастут до нескольких тысяч за пару месяцев).

У меня есть сценарий использования, когда каждый раз новый пользовательский документ Созданный в / users / collection, я хочу, чтобы все документы из мастера были скопированы в /users/ndomuserId‹/.

. Для этого я создал облачную функцию Firebase, как показано ниже:

// setup for new user
exports.setupCollectionForUser = functions.firestore
  .document('users/{userId}')
  .onCreate((snap, context) => {

    const userId = context.params.userId;

    db.collection('master').get().then(snapshot => {

      if (snapshot.empty) {
        console.log('no docs found');
        return;
      }

      snapshot.forEach(function(doc) {

        return db.collection('users').doc(userId).collection('slave').doc(doc.get('uid')).set(doc.data());
      });
    });
 });

Это работает, единственная проблема в том, что это займет вечность (~ 3-5 минут) только для примерно 200 документов. Это был такой облом, потому что многое зависит от того, как быстро копируются эти документы. Я надеялся, что это будет максимум несколько секунд. Кроме того, документы отображаются полностью, а не так, как они написаны, или, по крайней мере, они так выглядят.

Я что-то не так делаю? Почему это занимает так много времени?

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

Пожалуйста, сообщите.

1 Ответ

1 голос
/ 07 февраля 2020

Если я не ошибаюсь, при правильном управлении параллельными записями с помощью Promise.all() и возврате цепочки обещаний это обычно должно улучшить скорость.

Попробуйте адаптировать свой код следующим образом:

exports.setupCollectionForUser = functions.firestore
    .document('users/{userId}')
    .onCreate((snap, context) => {

        const userId = context.params.userId;

        return db.collection('master').get().then(snapshot => {  

            if (snapshot.empty) {
                console.log('no docs found');
                return null;
            } else {

                const promises = [];
                const slaveRef = db.collection('users').doc(userId).collection('slave');
                snapshot.forEach(doc => {

                      promises.push(slaveRef.doc(doc.get('uid')).set(doc.data()))

                });

                return Promise.all(promises);

            }

        });

    });

Я бы посоветовал вам посмотреть 3 видео о "JavaScript Promises" из серии Firebase , который объясняет, почему так важно возвращать Обещание или значение в фоновой облачной функции.


Обратите внимание, что если вы уверены, что у вас есть менее 500 документов для сохранения в slave collection, вы можете использовать пакетную запись . (Вы можете использовать его для более чем 500 документов, но тогда вам придется управлять различными партиями пакетной записи ...)

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