Я много читал на эту тему и думаю, что что-то основное ускользает от меня. Проблема в том, что несмотря на то, что я обрабатываю null
значения, подсчитанный объект увеличивается случайным образом. Например, у меня есть объект reports
, где я храню отчеты. Каждый раз, когда один из них создается или удаляется, запускается транзакция, которая обновляет другой объект, который содержит значение общих отчетов (и некоторую другую статистику). Этот счет НЕ отражает реальное значение счета отчетов ...
Некоторый код (обратите внимание, что я удалил его, чтобы сделать его меньше):
'use strict';
// Firebase Functions & Admin
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const _ = require('lodash');
const moment = require('moment');
try {
admin.initializeApp(functions.config().firebase);
} catch (e) {
}
exports = module.exports = functions.database.ref('/reports/{pushId}').onCreate(event => {
let report = event.data.val();
const collectionRef = event.data.ref.parent;
if (report === null) {
report = event.data.previous.val();
if (report === null) {
return false;
}
}
let category = report.category,
subject = report.subject,
created_user_key = report.created_user_key;
// count for categories
if (typeof category !== 'undefined') {
const countCategoryRef = collectionRef.root.child('/categories/' + category + '/reports');
countCategoryRef.transaction(current => {
if (event.data.exists() && !event.data.previous.exists()) {
return (current || 0) + 1;
} else if (!event.data.exists() && event.data.previous.exists()) {
return (current || 1) - 1;
} else {
return null;
}
});
// count for subjects
if (typeof subject !== 'undefined') {
const countCategorySubjectRef = collectionRef.root.child('/categories/' + category + '/subjects/' + subject + '/reports');
countCategorySubjectRef.transaction(current => {
if (event.data.exists() && !event.data.previous.exists()) {
return (current || 0) + 1;
} else if (!event.data.exists() && event.data.previous.exists()) {
return (current || 1) - 1;
} else {
return null;
}
});
}
}
// count for users
if (typeof created_user_key !== 'undefined') {
const countUsersRef = collectionRef.root.child('/users/' + created_user_key + '/created_reports');
countUsersRef.transaction(current => {
if (event.data.exists() && !event.data.previous.exists()) {
return (current || 0) + 1;
} else if (!event.data.exists() && event.data.previous.exists()) {
return (current || 1) - 1;
} else {
return null;
}
});
}
// count for reports_count
const countReportsCount = collectionRef.root.child('/reports_count/' + moment().format('Y'));
countReportsCount.transaction(current => {
if (event.data.exists() && !event.data.previous.exists()) {
return (current || 0) + 1;
} else if (!event.data.exists() && event.data.previous.exists()) {
return (current || 1) - 1;
} else {
return null;
}
});
return true;
});
.onDelete()
в основном то же самое. Не хотел использовать .onWrite()
, потому что я обрабатываю отчеты, и подсчет будет запускаться несколько раз.
Объект JSON (просто пример того, как он выглядит):
{
"categories" : {
"Handhaving~2FBOA" : {
"icon" : "assets/img/icons/deeppurple.png",
"marker_color" : "#6200ea",
"reports" : 7,
"subjects" : {
"Bijtincidenten honden" : {
"category" : "Handhaving~2FBOA",
"reports" : 2,
"user_display_name" : "..",
"user_key" : ".."
},
"More ...": {...}
}
},
"More ...": {...}
},
"categories_reports" : {
"Handhaving~2FBOA" : {
"-LBUuwvqghbbimujwJvg" : true,
"-LBUxS7penGMgOYkIuE7" : true,
"-LBV5BZLzGR5ccsiG0QG" : true,
"-LBVrBMK4y0lMD956ueE" : true,
"-LBVwtex93d8QoESLZmm" : true,
"-LBWhARzV1g7m3eGJ7lm" : true,
"-LBY0q-ZVeEpk8rm6-V9" : true
},
"More ...": {...}
},
"reports" : {
"-L9nlUmC0V_EYWLnuoJJ" : {...},
"-L9nsxJWvQwh4MuTVXXZ" : {...},
"-L9nuLPniqAC7gY4wkas" : {...},
"More ...": {...}
},
"reports_count" : {
"2018" : 964
},
"users" : {
"41XQpZiURaZwmTNS9Ee6ulFNhRo2" : {
"assigned_reports" : 16,
"created_reports" : 0,
"display_name" : "..",
"email" : "..",
"notes" : "",
"rejected_reports" : 1,
"resolved_reports" : 0,
"type" : "admin"
},
"4xwxr6wPfTTaasXJeE6sdxSjefK2" : {
"assigned_reports" : 0,
"display_name" : "..",
"email" : "..",
"notes" : "",
"rejected_reports" : 0,
"resolved_reports" : 0,
"type" : "viewer"
},
"More ...": {...}
},
"users_assigned_reports" : {
"41XQpZiURaZwmTNS9Ee6ulFNhRo2" : {
"-L9ynqHoO3C-r4TEDA_6" : true,
"-LAHtIf6C2ji49nbmK22" : true,
"More ...": {...}
},
"More ...": {...}
},
"users_created_reports" : {
"C4I4djpcQLXOpnLciMTH7TPes242" : {
"-LBWhARzV1g7m3eGJ7lm" : true,
"-LBWhcVGV5zsfjsl1ns1" : true
},
"More ...": {...}
},
"users_resolved_reports" : {
"6KZHvuXF29VEA0FRSptRdCMAHBo1" : {
"-L9nsxJWvQwh4MuTVXXZ" : true,
"-L9p86RLiNMeGF_TyzJ9" : true,
},
"More ...": {...}
}
}
Как вы можете видеть reports_count
объект утверждает, что есть 964 отчета, но на самом деле их всего около 300.
Итак, как поддерживать порядок транзакций и заставлять их фактически и правильно подсчитывать добавленные / удаленные объекты?
Или есть лучший и самый важный, более надежный способ подсчета фактического количества отчетов? Я думал о том, чтобы считать каждый раз, когда отчет добавляется / удаляется, таким образом я получал бы более надежные результаты, но я боюсь, что произойдет, если два или более пользователей будут создавать / удалять отчеты одновременно.