Написание 4 возвратов для одного триггера, каждый из которых возвращает разные docRef.

avatar
Michael Vish
8 апреля 2018 в 02:50
317
2
0

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

например, для статистики, добавив новый документ о спортивных сессиях в коллекцию сессий. он обновит документы: yearlyStats, quartlyStats, monthStats и dailyStats.

поэтому вопрос, как я пишу 4 возврата для одного триггера, что каждый возврат относится к разным docRef.

Нужно ли мне писать 4 отдельные функции с одним и тем же триггером? или я могу сделать все это в одной функции?

Источник

Ответы (2)

avatar
Jason Berryman
9 апреля 2018 в 01:58
2

Если вы обновляете статистику на основе новых созданных документов, вам лучше использовать транзакции. Таким образом, вы гарантируете, что 2 одновременных создания документов не будут одновременно обновлять документы статистики. Вы можете сделать так, чтобы транзакция считывала значение из нового документа, а затем обновляла несколько документов.

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

Документацию для обоих вариантов можно найти здесь, Транзакции и пакетная запись.

Имейте в виду, что при обоих вариантах вы можете обновлять только один документ со скоростью один раз в секунду. Если вы обрабатываете большое количество документов, вам может быть лучше передать данные нового документа в Cloud Dataflow (через PubSub из вашей облачной функции), а затем передавать регулярные обновления обратно в Cloud Firestore. Если это ваш вариант использования, то это видео будет вам полезно... Конвейеры данных с Firebase и Google Cloud

Пример кода с использованием транзакции и getAll

Для этого требуется Node SDK 0.12.0 или выше (Admin SDK >= 5.9.1)

const firestore = firebase.firestore();

let firstDocRef = firestore.doc('myCollection/document1');
let secondDocRef = firestore.doc('myCollection/document2');

return firestore.runTransaction(t => {
  return t.getAll(firstDocRef, secondDocRef).then(querySnapshot => {

    // Return just the data and map it to firstDoc and secondDoc (personal hack)
    querySnapshot = querySnapshot.map(doc => doc.data());
    let [firstDocData, secondDocData] = querySnapshot;

    // Increment the counters
    let firstUpdate = {myCounter: firstDocData.myCounter + 1};
    let secondUpdate = {myCounter: secondDocData.myCounter + 1};

    // Write the new data back to Cloud Firestore
    t.update(firstDocRef, firstUpdate);
    t.update(secondDocRef, secondUpdate);

  });
})
.then(() => {
  console.log('Transaction completed successfully');
})
.catch(err => {
  console.error(err);
});
Michael Vish
10 апреля 2018 в 18:27
0

Запись с использованием пакетной опции для документов — хороший вариант, но, поскольку эти поля являются счетчиками, поэтому перед обновлением мне нужно будет прочитать их из документов. Пакетная опция позволяет это? (прочитайте пару документов, а затем используйте пакет для обновления документов)

Jason Berryman
10 апреля 2018 в 18:49
0

Вы можете прочитать несколько документов в транзакции, используя transaction.getAll. Когда у вас есть все документы, просто обновите документы по мере необходимости в рамках транзакции, прежде чем вернуться к функции. В документации есть ошибка (сообщено). В массив должны попасть объекты 0 и 1, а не 1 и 2.

Michael Vish
11 апреля 2018 в 18:21
0

Могу ли я использовать writeBatch внутри транзакции? Я пытаюсь это сделать, но он возвращает мне «Функция вернула неопределенное значение, ожидаемое обещание или значение». если это возможно, то как закрыть эту функцию транзакции после writeBatch.commit(); команда ??

Jason Berryman
11 апреля 2018 в 21:40
0

Я добавил пример кода в свой ответ. Надеюсь, это должно помочь

Jason Berryman
11 апреля 2018 в 22:02
0

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

Michael Vish
12 апреля 2018 в 10:02
0

Работает, спасибо за пример кода, очень помог.

avatar
Frank van Puffelen
8 апреля 2018 в 03:53
1

Вы делаете это, объединяя промисы из четырех операций записи в вызов Promise.all() и возвращая его из своей функции.

Посмотрите на Promise.all() документацию MDN или на некоторые из предыдущих вопросов, где использовался Promise.all().