Вот код транзакции Firestore, которая запишет новый документ Screen и обновит счетчики nbrScreens
в родительских документах Formation, Module и Chapter соответственно.
Это полная HTML-страница,Выполните следующие действия:
1 / Адаптируйте значения конфигурации Firebase в HTML.
2 / Создайте в Firestore родительские коллекции и документы с нужными идентификаторами.
3 / Для каждого документа (формация, модуль и глава) добавьте поле типа номер с именем nbrScreens
со значением 0
4 / Адаптируйте на странице HTML значение screenId
, screenData
и параметры функции setNewScreen()
вызывают то, что вам нужно.
5 / Откройте страницу в браузере (например, локально), функция будет вызвана и транзакция выполнена
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://www.gstatic.com/firebasejs/5.0.4/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.0.4/firebase-firestore.js"></script>
</head>
<body>
<script>
var config = {
apiKey: "...",
authDomain: "...",
databaseURL: "...",
projectId: "..."
};
firebase.initializeApp(config);
var firestoredb = firebase.firestore();
function setNewScreen(formationId, moduleId, chapterId, screenId, screenData) {
var formationDocRef = firestoredb.collection("Formations").doc(formationId);
var moduleDocRef = formationDocRef.collection("Modules").doc(moduleId);
var chapterDocRef = moduleDocRef.collection("Chapters").doc(chapterId);
var screenDocRef = chapterDocRef.collection("Screens").doc(screenId);
return firestoredb.runTransaction(function (transaction) {
var newChaptersNbrScreens;
var newModulesNbrScreens;
var newFormationsNbrScreens;
return transaction.get(chapterDocRef)
.then(function (sfDoc) {
if (!sfDoc.exists) {
throw "Document Chapter does not exist!";
}
newChaptersNbrScreens = sfDoc.data().nbrScreens + 1;
return transaction.get(moduleDocRef);
})
.then(function (sfDoc) {
if (!sfDoc.exists) {
throw "Document Module does not exist!";
}
newModulesNbrScreens = sfDoc.data().nbrScreens + 1;
return transaction.get(formationDocRef);
})
.then(function (sfDoc) {
if (!sfDoc.exists) {
throw "Document Formation does not exist!";
}
newFormationsNbrScreens = sfDoc.data().nbrScreens + 1;
return transaction
.set(formationDocRef, {nbrScreens: newFormationsNbrScreens}, { merge: true })
.set(moduleDocRef, {nbrScreens: newModulesNbrScreens}, { merge: true })
.set(chapterDocRef, {nbrScreens: newChaptersNbrScreens}, { merge: true })
.set(screenDocRef, screenData)
});
});
}
//Calling the function
//The formation, module and chapter docs must be created before calling it!!
var screenId = 's1';
var screenData = {title: 'screenTitle_s1', content: 'foo'};
setNewScreen("f1", "m1", "c1", screenId, screenData) //Screen will be saved under Formation f1, Module m1 and Chapter c1
.then(function () {
console.log("Transaction successfully committed!");
})
.catch(function (error) {
console.log("Transaction failed: ", error);
});
</script>
</body>
</html>
Обратите внимание, что вы можете адаптировать код для создания Формации, Модуля и Главы.На самом деле это не может быть сделано в транзакции , потому что все операции чтения должны выполняться до записи (записей) .
. Вы могли бы что-то вроде (псевдокод):
FormationDocumentReference.set({}) // <- returns a promise
.then(function() {
ModuleDocumentReference.set({}) // <- returns a promise
})
.then(function() {
ChapterDocumentReference.set({}) // <- returns a promise
})
.then(function() {
setNewScreen(id_f, id_m1, id_c1, screenId, screenData) // <- returns a promise
.then(function () {
console.log("Transaction successfully committed!");
})
.catch(function (error) {
console.log("Transaction failed: ", error);
});
Наконец, вот пара примечательных моментов, касающихся приведенного выше кода транзакции:
1 / transaction.get()
возвращает обещание, содержащее ненулевое firebase.firestore.DocumentSnapshot
, как объяснено здесь .Поэтому вы должны связать их с помощью then()
.
2 / С другой стороны, transaction.set()
возвращает «Этот экземпляр транзакции», см. здесь .Поэтому вы должны просто цеплять их один за другим (например, return transaction.set().set()...
)