如何在Firebase中正确地反规范化数据

时间:2016-02-20 20:25:44

标签: android firebase denormalization

我是NoSQL和非规范化的新手。但是,我希望允许我的应用中SignUp处的操作定义为:

  1. 如果已经使用了用户名,则不允许用户使用它
  2. 如果已经使用了电话号码,则不允许用户使用
  3. 允许新用户同步"同步"他们的电话号码与服务器联系以确定谁是目前的用户,并检索他们各自的uid
  4. 我的架构概述如下,因为很快就需要检查用户注册时是否已经存在用户名/电话号码,以及新用户联系人电话号码是否与用户链接时所需的搜索和比较已存在于应用内:

    {
      "presentUsersByPhoneNumber" : {
        "1614#######" : {
          "uid" : "fdb17f3a-7b7d-4aa5-9a0b-b9fb33c349de"
        },
        "1614#######" : {
          "uid" : "99e4989b-a046-4c5f-9478-5ebd8bdc3ded"
        },
        "1614#######" : {
          "uid" : "1783917f-00e4-47a0-b2cd-987bdf185129"
        },
        "1614#######" : {
          "uid" : "a96da7b1-7c4e-44bc-b82e-fc75bed52bcd"
        }
      },
      "presentUsersByUsername" : {
        "ak" : {
          "uid" : "a96da7b1-7c4e-44bc-b82e-fc75bed52bcd"
        },
        "ak2" : {
          "uid" : "99e4989b-a046-4c5f-9478-5ebd8bdc3ded"
        },
        "ak3" : {
          "uid" : "1783917f-00e4-47a0-b2cd-987bdf185129"
        },
        "kja" : {
          "uid" : "fdb17f3a-7b7d-4aa5-9a0b-b9fb33c349de"
        }
      },
      "users" : {
        "1783917f-00e4-47a0-b2cd-987bdf185129" : {
          "phoneNumber" : "614#######",
          "username" : "ak3"
        },
        "99e4989b-a046-4c5f-9478-5ebd8bdc3ded" : {
          "phoneNumber" : "1614#######",
          "username" : "ak2"
        },
        "a96da7b1-7c4e-44bc-b82e-fc75bed52bcd" : {
          "phoneNumber" : "1614#######",
          "username" : "ak1"
        },
        "fdb17f3a-7b7d-4aa5-9a0b-b9fb33c349de" : {
          "phoneNumber" : "1614#######",
          "username" : "kja"
        }
      }
    }
    

    这种方法在denormalizaiton的行为中是否过于公平?

1 个答案:

答案 0 :(得分:1)

在NoSQL中,您应该为应用程序访问它的方式建模数据。有关详细信息,请阅读此article on NoSQL data modeling

因此,如果您需要一种有效的方法来检查是否已经使用了电话号码或用户名,那么为这些存储映射是有意义的。我唯一可能做的就是将它们存储为简单的类型:

"phoneNumberToUid" : {
    "1614#######" : "fdb17f3a-7b7d-4aa5-9a0b-b9fb33c349de"
    "1614#######" : "99e4989b-a046-4c5f-9478-5ebd8bdc3ded"
},
"usernameToUid" : {
    "ak" : "a96da7b1-7c4e-44bc-b82e-fc75bed52bcd"
    "ak2" : "99e4989b-a046-4c5f-9478-5ebd8bdc3ded"
}

我在示例数据中注意到的一件事是ak中有一个键presentUsersByUsername,但users中没有相应的子name。这通常是因为您的代码要么中途中止,要么因为您在开发过程中的某个时刻犯了错误。

您可以通过以下方式预防许多这些问题:

  1. 使用多位置更新,以便将所有写入作为单个命令发送到Firebase

    ref.update({
      '/users/a96da7b1-7c4e-44bc-b82e-fc75bed52bcd/username': 'ak1',
      '/usernameToUid/ak': null,
      '/usernameToUid/ak1': 'a96da7b1-7c4e-44bc-b82e-fc75bed52bcd'
    });
    

    此更新是将用户名称从ak更改为ak1,删除旧映射并添加新映射的最安全方式。

  2. 使用验证规则可确保每个名称的用户都存在

    "usernameToUid": {
      "$username": {
        ".validate": "newData.parent().parent().child(newData.va()).child('username').val() == $username"
      }
    }