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

Итак, я пытаюсь реализовать новую облачную функцию для моего приложения, но она требует небольшой корректировки моей существующей модели данных базы данных.У каждого пользователя в моей базе данных есть поле, которое я пытаюсь обновлять каждую неделю.Я не хочу, чтобы эта функция запускалась для всех пользователей каждую неделю, поскольку это было бы излишне дорогой операцией.Вместо этого я просто решил отследить, когда в последний раз я обновлял этого пользователя, сохранив поле «последнее обновление» в его пользовательском документе.

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

Я думал об использовании «пакетной записи», как описано здесь: https://firebase.google.com/docs/firestore/manage-data/transactions#batched-writes

, но кажется, что вам нужно указать идентификатор каждого документа, который вы хотите обновить.У всех моих пользователей есть UUID, который был сгенерирован Firestore, поэтому мне не очень удобно вручную писать каждому пользователю.Есть ли способ для меня, чтобы создать новое поле в каждом документе существующей коллекции?Или, если не возможно, для меня получить список всех идентификаторов документов, чтобы я мог перебрать его и сделать действительно уродливую пакетную запись?Мне нужно сделать это массовое обновление только один раз, а потом уже никогда.Если я не найду новый фрагмент данных, который я бы хотел отслеживать.

1 Ответ

0 голосов
/ 31 января 2019

Вы можете использовать облачную функцию: например, ниже вы найдете код облачной функции, который вы бы вызвали, создав документ в коллекции с именем batchUpdateTrigger (обратите внимание, что это просто способ вызвать облачную функцию. Для этого вы вполне могли бы использовать облачную функцию HTTPS.

В этой облачной функции мы берем все документы из коллекции с именем collection и добавляем в каждое из них новое поле с текущей датой./ время (ServerValue.TIMESTAMP).Мы используем Promise.all() для параллельного выполнения всей асинхронной работы по обновлению.Не забудьте добавить доступ на запись в коллекцию batchUpdateTrigger и удалить облачную функцию после ее запуска.

 exports.batchUpdate = functions.firestore
  .document('batchUpdateTrigger/{triggerId}')
  .onCreate((snap, context) => {

    var collecRef = db.collection('collection');
    return admin.collecRef.get()
        .then(snapshot => {

           const ts = admin.database.ServerValue.TIMESTAMP;
           var promises = [];

           snapshot.forEach(doc => {
             const ref = doc.ref;

             promises.push(
               ref.update({
                   lastUpdate: ts
               });
             );

           });

           return Promise.all(promises);

        });

  });

Одна из проблем, с которой вы можете здесь столкнуться, состоит в том, что вы достигаете тайм-аута облачной функции.,Время ожидания по умолчанию составляет 60 секунд, но вы можете увеличить его в консоли Google Cloud (https://console.cloud.google.com/functions/list?project=xxxxxxx)


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

В этом случае облачная функция будет выглядеть следующим образом:

 exports.batchUpdate = functions.firestore
  .document('batchUpdateTrigger/{triggerId}')
  .onCreate((snap, context) => {

    var collecRef = db.collection('collection');
    return admin.collecRef.get()
        .then(snapshot => {

           const ts = admin.database.ServerValue.TIMESTAMP;
           let batch = db.batch();

           snapshot.forEach(doc => {
             const ref = doc.ref;

             batch.update(ref, {
                   lastUpdate: ts
               });

           });

           return batch.commit();

        });

  });

Однако вам потребуется в коде управлять максимальным пределом в 500 операций в пакете .

Ниже приведен возможный простой подход (т. Е. Не очень сложный ...). Поскольку вы будете устанавливать значения по умолчанию только один раз, и у вас будет всего несколько сотен документов наМы можем считать это приемлемым! Следующая облачная функция будет обрабатывать документы с партией от 500. Поэтому вам, возможно, придется вручную повторно запускать ее, пока не будут обработаны все документы.

 exports.batchUpdate = functions.firestore
  .document('batchUpdateTrigger/{triggerId}')
  .onCreate((snap, context) => {

    var collecRef = db.collection('collection');
    return admin.collecRef.get()
        .then(snapshot => {

           const docRefsArray = [];
           snapshot.forEach(doc => {
              if (doc.data().lastUpdate == null) {
                 //We need to "treat" this doc
                 docRefsArray.push(doc.ref);
              )
            });

            console.log("Nbr of doc to treat: " + docRefsArray.length); //When the output is 0 you are done, i.e. all the docs are treated

            if (docRefsArray.length > 0) {

                const ts = admin.database.ServerValue.TIMESTAMP;

                let batch = db.batch();

                if (docRefsArray.length < 500) {

                   //We can "treat" all the documents in the QuerySnapshot
                   docRefsArray.forEach(ref => {
                      batch.update(ref, {
                         lastUpdate: ts
                      });
                   });

                } else {

                   //We need to "treat" only 500 documents
                   for (let i = 0; i < 500; i++) {
                      batch.update(docRefsArray[i], {
                         lastUpdate: ts
                      });
                }

                ​return batch.commit();

            } else {
                return null;
            }
        });
  });

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

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