У меня есть школьный предмет с классами и учениками. Студенты - это подгруппа каждой семьи. При создании школы я пишу несколько сотен семей в нескольких сериях записей.
Создавая каждого учащегося, я хочу сделать несколько вещей:
- обновить строку в семье учащегося содержит имена учеников
- ученики содержат идентификатор класса, и я sh обновлю класс с некоторыми данными ученика
- школа ведет отдельный список учеников для удобства поиска, и Я хочу добавить туда студентов
Этот код выглядит следующим образом ...
exports.didCreateStudent = functions.firestore.document(studentPath).onCreate((snap, context) => {
return Promise.all([
updateFamilyNames(snap.ref.parent.parent),
updateClassroomStudent(snap, null, snap.data().classroom),
updateStudentCollection(null, snap)
])
})
Каждая из этих функций выполняет транзакцию. Первый получает семью ученика и пишет имена детей, второй делает то же самое в классе ученика и так далее. (Я делаю это также и для триггеров, чтобы узнать поведение обновлений и удалений).
Например, существенная часть updateClassroomStudent
выглядит следующим образом ...
return transaction.get(classroomDocRef).then(snapshot => {
const student = Object.assign({}, _.pick(studentSnapshot.data(), 'firstName', 'lastName', 'grade'), { ref: studentSnapshot.ref })
const addition = { students: { [studentSnapshot.id]: student } }
return transaction.set(snapshot.ref, addition, { merge: true })
})
Это хорошо работает для небольших школ (10 семей, примерно по 2 ученика в каждой), но в больших школах (100 семей) я начинаю видеть Error: 10 ABORTED: Too much contention on these documents. Please try again.
Я могу избежать ошибок, пропустив оба updateClassroomStudent
и updateStudentCollection
, но нет, если я разрешу запускать один (или оба).
Поможет ли это не использовать транзакции? Когда несколько сотен документов создаются с помощью пакета записи (например, семей учеников), триггеры onCreate
будут работать последовательно? Если это так, возможно, я могу пропустить транзакцию и сэкономить некоторые накладные расходы, возможно, просто сделать паузу между партиями.