Как я могу обновить более 500 документов в Firestore с помощью Batch? - PullRequest
0 голосов
/ 04 сентября 2018

Я пытаюсь обновить поле timestamp с отметкой времени администратора Firestore в коллекции, содержащей более 500 документов.

const batch = db.batch();
const serverTimestamp = admin.firestore.FieldValue.serverTimestamp();

db
  .collection('My Collection')
  .get()
  .then((docs) => {
    serverTimestamp,
  }, {
    merge: true,
  })
  .then(() => res.send('All docs updated'))
  .catch(console.error);

Это выдает ошибку

{ Error: 3 INVALID_ARGUMENT: cannot write more than 500 entities in a single call
    at Object.exports.createStatusError (C:\Users\Growthfile\Desktop\cf-test\functions\node_modules\grpc\src\common.js:87:15)
    at Object.onReceiveStatus (C:\Users\Growthfile\Desktop\cf-test\functions\node_modules\grpc\src\client_interceptors.js:1188:28)
    at InterceptingListener._callNext (C:\Users\Growthfile\Desktop\cf-test\functions\node_modules\grpc\src\client_interceptors.js:564:42)
    at InterceptingListener.onReceiveStatus (C:\Users\Growthfile\Desktop\cf-test\functions\node_modules\grpc\src\client_interceptors.js:614:8)
    at callback (C:\Users\Growthfile\Desktop\cf-test\functions\node_modules\grpc\src\client_interceptors.js:841:24)
  code: 3,
  metadata: Metadata { _internal_repr: {} },
  details: 'cannot write more than 500 entities in a single call' }

Есть ли способ, которым я могу написать рекурсивный метод, который создает пакетный объект, обновляющий пакет из 500 документов по одному, пока все документы не будут обновлены.

Из документации я знаю, что операция удаления возможна при рекурсивном подходе, как упомянуто здесь:

https://firebase.google.com/docs/firestore/manage-data/delete-data#collections

Но для обновления я не уверен, как завершить выполнение, так как документы не удаляются.

Ответы [ 2 ]

0 голосов
/ 15 мая 2019

Я также столкнулся с проблемой обновления более 500 документов в коллекции Firestore. И я хотел бы поделиться тем, как я решил эту проблему.

Я использую облачные функции для обновления своей коллекции в Firestore, но это также должно работать с кодом на стороне клиента.

Решение подсчитывает каждую операцию, выполненную для партии, и после достижения предела создается новая партия, которая передается в batchArray.

После того, как все обновления завершены, код перебирает batchArray и фиксирует каждый пакет, который находится внутри массива.

важно сосчитать каждую операцию set(), update(), delete(), которая выполняется в пакете, поскольку все они рассчитывают до предела 500 операций.

const documentSnapshotArray = await firestore.collection('my-collection').get();

const batchArray = [];
batchArray.push(firestore.batch());
let operationCounter = 0;
let batchIndex = 0;

documentSnapshotArray.forEach(documentSnapshot => {
    const documentData = documentSnapshot.data();

    // update document data here...

    batchArray[batchIndex].update(documentSnapshot.ref, documentData);
    operationCounter++;

    if (operationCounter === 499) {
      batchArray.push(firestore.batch());
      batchIndex++;
      operationCounter = 0;
    }
});

batchArray.forEach(async batch => await batch.commit());

return;
0 голосов
/ 04 сентября 2018

Ваше решение на самом деле не будет "рекурсивным". Если вы хотите обновить пакет более чем 500 документами, вам нужно будет выполнить итерацию документов, создать пакеты из 500 или менее самостоятельно, а затем зафиксировать пакеты индивидуально. Или вы можете просто обновить каждый документ по отдельности, поскольку в вашей ситуации может не быть реальной необходимости в пакетах.

...