Firebase功能 - 实时数据库和事务

时间:2018-05-08 15:07:53

标签: firebase firebase-realtime-database google-cloud-functions firebase-admin

我已经阅读了很多关于这个主题的内容,我认为基本的东西正在躲避我。问题在于,尽管我处理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个。

那么,如何保持事务顺序并强制它们实际正确地计算添加/删除的对象? 或者是否有更好,最重要,更可靠的方法来计算实际报告数量?我想在每次添加/删除报告时计算,这样我会得到更可靠的结果,但我担心如果两个或更多用户同时创建/删除报告会发生什么。

0 个答案:

没有答案