TL; DR Должен ли я использовать Transaction.getAll()
или использовать цикл for и обновлять документы по одному, используя Transaction.get()
рассмотрим следующую схему:
- someTopLevelCollection
- accountId1
- projects
- tasks
- users
- accountId2
- projects
- tasks
- users
Всякий раз, когда проект / задача создается в проектах, соответственно подгруппе задач, счетчики в коллекции пользователей обновляются, скажем, projectsCount и tasksCount.
Ссылки на пользователей хранятся внутри проекта и задач в виде массива userIds следующим образом:
Примечание: другие поля удалены для краткости
структура проекта / задачи:
{
"name": "someName",
"status": "someStatus",
"users": [
"userId1",
"userId2",
....
],
...
}
Теперь мне нужно обновить, скажем, счетчик для всех пользовательских идентификаторов в массиве пользователей, используя транзакцию.
Метод 1:
const accountId = context.params.accountId;
const userIds = snapshot.data().users;
userIds.forEach(userId => {
const userDocRef = db.collection(someTopLevelCollection)
.doc(accountId)
.collection('users')
.doc(userId);
let transaction = db.runTransaction(transaction => {
return transaction.get(userDocRef)
.then(doc => {
const snapshotData = doc.data();
let newCounterValue = snapshotData[counterName] + 1;
transaction.update(userDocRef, {counterName: newCounterValue});
return Promise.resolve(`Incremented ${counterName} to ${newCounterValue}`);
});
}).then(result => {
console.log('Transaction success!', result);
return true;
}).catch(err => {
console.error('Transaction failure:', err);
return false;
});
});
Метод 2:
const accountId = context.params.accountId;
const userIds = snapshot.data().users;
let userDocRefs = [];
userIds.forEach(userId => {
const userDocRef = db.collection(someTopLevelCollection)
.doc(accountId)
.collection('users')
.doc(userId);
userDocRefs.push(userDocRef)
});
let transaction = db.runTransaction(transaction => {
return transaction.getAll(userDocRefs)
.then(docs => {
docs.forEach(doc => {
const snapshotData = doc.data();
let newCounterValue = snapshotData[counterName] + 1;
transaction.update(doc.ref, {counterName: newCounterValue});
});
return Promise.resolve('Completed transaction successfully');
});
}).then(result => {
console.log('Transaction success!', result);
return true;
}).catch(err => {
console.error('Transaction failure:', err);
return false;
});
Ниже приведены мои вопросы:
- когда внешнее изменение документа происходит, когда
getAll()
находится под
выполнение, - все документы, выбранные снова для поддержки
Консистенция . Если да, то какой вариант использования getAll ()?
- Когда транзакция запускается одна за другой с использованием цикла for и
изменение документа происходит внешне по отношению к текущему документу
изменено в транзакции, - транзакция повторена только для этого
документ
Спасибо.