热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

在Firebase中对私有数据访问的数据结构进行非规范化处理?

如何解决《在Firebase中对私有数据访问的数据结构进行非规范化处理?》经验,为你挑选了1个好方法。

我想创建可扩展的数据(跟踪用户的私人数据).

Firebase文档建议将子对象嵌套在父对象下,如下所示:

{
  "users": {
    "google:1234567890": {
      "displayName" : "Username A",
      "provider" : "google",
      "provider_id" : "1234567890",
      "todos": {
          "rec_id1": "Walk the dog",
          "rec_id2": "Buy milk",
          "rec_id3": "Win a gold medal in the Olympics",
          ...
      }
    }, ...
  }
}

(其中rec_id是Firebase.push()生成的唯一键.)

但正如Denormalizing Your Data is Normal中提到的那样,我认为以这种方式构造它会更好:

{
  "users" : {
    "google:1234567890" : {
      "displayName" : "Username A",
      "provider" : "google",
      "provider_id" : "1234567890"
    }, ...
  },
  "todos" : {
    "google:1234567890" : {
      "rec_id1" : {
        "todo" : "Walk the dog"
      },
      "rec_id2" : {
        "todo" : "Buy milk"
      },
      "rec_id3" : {
        "todo" : "Win a gold medal in the Olympics"
      }, ...
    }, ...
  }
}

然后只允许用户写入/读取它自己的数据应用以下安全规则:

{
  "rules": {
    "users": {
      "$uid": {
        // grants write and read access to the owner of this user account whose uid must exactly match the key ($uid)
        ".write": "auth !== null && auth.uid === $uid",
        ".read": "auth !== null && auth.uid === $uid"
      }
    },
    "todos": {
      "$uid": {
        // grants write and read access to the owner of this user account whose uid must exactly match the key ($uid)
        ".write": "auth !== null && auth.uid === $uid",
        ".read": "auth !== null && auth.uid === $uid"
      }
    }
  }
}

由于我是这类数据库的新手,我想知道是否有任何缺点我想要构建它的方式.

如第一个例子中所推荐的那样,将所有待办事项直接嵌套在用户下面会更好吗?



1> Sinan Bolel..:

首先,如果你还没有遇到过几个资源:

Firebase文档中"入门指南"的"构建数据"部分?

正如您所说,该指南的"创建可扩展的数据"部分是重要的部分.

另外,请查看"关于Firebase非规范化博客文章的澄清"的答案

编辑:你显然遇到了这些资源,因为它在你的问题中已经链接了,但我建议你多阅读一下"构建你的数据"指南.

编辑2:看到这个答案 @Frank van Puffelen发布在In firebase中,使用单独的端点建模许多关系是一个好主意吗?

而且这个

我还建议阅读规范化[1] [2]和非规范化[3] [4],我认为可能存在一些混淆,两者中你指的是哪一个.


这将我们带到你的场景......

您设置数据的两种方式实际上完成了同样的事情!

但是,您会注意到,第一个示例实际上是在"构建您的数据"指南中列为反模式.

如果要加载用户数据,然后在不同时间加载该用户,则以第二种方式执行此操作将非常有用.

如果您只有一个用户访问每个待办事项列表,那么设置它的方式很好.

例如,我在应用程序中执行此操作,我知道每个用户在历史记录列表中只有一个位置,我只想在某些情况下加载用户的历史记录.

/users/$userUid给我用户数据并/history/$userUid给我用户的历史记录.

它可以轻松分割加载.

但是,如果todo列表在不同用户之间共享并且必须从多个源更新,则此结构不会带来任何好处.

如果您想要共享访问,那么您就是在正确的轨道上,只需要使用密钥作为参考.


不同的方法是:

/todos/$uid您可以将新todo对象推送到新的对象,/todos以便获取新的唯一ID(称为密钥),而不是在其下显式设置待办事项对象.

然后,将该键添加到正确user对象的todos子项中.

这将允许您首先加载用户的数据,并仅获取用户所属的待办事项的索引(键),以及

然后,您可以todos独立加载用户所属的所有内容.

这样做会:

防止用户对象变得庞大

允许多个用户更新单个用户todo,而无需在多个位置更新其子参数.

通过将其拆分为单独的路径来获得可伸缩数据.

以下是本指南"创建数据量表"部分的最后一个数据样本:( 我添加了一些评论)

  // An index to track Mary's memberships
  {
    "users": {
      "mchen": {
        "name": "Mary Chen",
        // index Mary's groups in her profile
        "groups": {
           // the value here doesn't matter, just that the key exists
           // these keys are used to figure out which groups should 
           // be loaded (at whatever appropriate time) for Mary,
           // without having to load all the group's data initially (just the keys). 
           "alpha": true,
           "charlie": true
        }
      },
      ...
    },
    // Here is /groups. In here, there would be a group with the key
    // 'alpha' and another one with the key 'charlie'. Once Mary's
    // data is loaded on the client, you would then proceed to load 
    // the groups from this list, since you know what keys to look for.
    "groups": { ... }
  }

这实现了更平坦的结构.

正如文件所说,

是.这是双向关系的必要冗余.它允许我们快速有效地获取Mary的成员资格,即使用户或组的列表可以扩展到数百万,或者安全和Firebase规则会阻止访问某些记录.


所以问题是,您的数据如何才能让用户拥有多个待办事项列表,这些列表也可以与其他用户共享?

这是一个例子:

{
  "users" : {
    "google:1234567890" : {
      "displayName" : "Username A",
      "provider" : "google",
      "provider_id" : "1234567890",
      "todoLists" : {
        "todoList1": true,
        "todoList2": true
      }
    },
    "google:0987654321" : {
      "displayName" : "Username B",
      "provider" : "google",
      "provider_id" : "0987654321",
      "todoLists" : {
        "todoList2": true
      }
    }
  },
  "todoLists" : {
    "todoList1" : {
      // 'members' user for rules
      "members" : {
        "google:1234567890" : true
      },
      "records" : {
        "rec_id1" : {
          "todo" : "Walk the dog",
          "createdAt" : "1426240376047"
        },
        "rec_id2" : {
          "todo" : "Buy milk",
          "createdAt" : "1426240376301"
        },
        "rec_id3" : {
          "todo" : "Win a gold medal in the Olympics",
          "createdAt" : "1426240376301"
        }
      }
    },
    "todoList2" : {
      "members" : {
        "google:1234567890" : true,
        "google:0987654321" : true
      },
      "records" : {
        "rec_id4" : {
          "todo" : "Get present",
          "createdAt" : "1426240388047"
        },
        "rec_id5" : {
          "todo" : "Run a mile",
          "createdAt" : "1426240399301"
        },
        "rec_id6" : {
          "todo" : "Pet a cat",
          "createdAt" : "1426240400301"
        }
      }
    }
  }
}

在这种情况下,用户A将加载两个列表,但用户B将仅加载第二个列表.如果你正确地设置规则,一切都会很好.

在操作中,您首先要加载用户的数据,然后在用户todoLists中加载每个待办事项列表, /todoList


但实际上,如果您正在创建一个应用程序,其中一个用户有一个todo列表,其中只有一个内容的待办事项,那么所有这些都是完全没必要的.

注意,这些"ID"应该是一个唯一的密钥,可以使用Firebase.push().

有关使用push生成新ID的信息,请参阅此答案.


总而言之,这完全取决于您的应用程序何时以及何时需要您的数据,数据更新频率以及由谁更新,以及最小化不必要的读取和观察者.空间通常很便宜,操作(和观察者)通常不是.

最后但同样重要的是,规则和安全是另一个非常重要的考虑因素 指南的最后一部分说:

"因此,索引速度更快,效率更高.后来,当我们谈论保护数据时,这种结构也非常重要.因为Security和Firebase规则不能在子节点列表上做任何"包含" ,我们将依赖广泛使用这样的密钥."


这是早期的,我希望我不是在喋喋不休,但是当我第一次从了解MySql到使用非结构化时,我遇到了同样的问题,所以我希望有所帮助!


推荐阅读
  • 解决Bootstrap DataTable Ajax请求重复问题
    在最近的一个项目中,我们使用了JQuery DataTable进行数据展示,虽然使用起来非常方便,但在测试过程中发现了一个问题:当查询条件改变时,有时查询结果的数据不正确。通过FireBug调试发现,点击搜索按钮时,会发送两次Ajax请求,一次是原条件的请求,一次是新条件的请求。 ... [详细]
  • 本文详细介绍了在 CentOS 7 系统中配置 fstab 文件以实现开机自动挂载 NFS 共享目录的方法,并解决了常见的配置失败问题。 ... [详细]
  • 本文节选自《NLTK基础教程——用NLTK和Python库构建机器学习应用》一书的第1章第1.2节,作者Nitin Hardeniya。本文将带领读者快速了解Python的基础知识,为后续的机器学习应用打下坚实的基础。 ... [详细]
  • 用阿里云的免费 SSL 证书让网站从 HTTP 换成 HTTPS
    HTTP协议是不加密传输数据的,也就是用户跟你的网站之间传递数据有可能在途中被截获,破解传递的真实内容,所以使用不加密的HTTP的网站是不 ... [详细]
  • Ihavetwomethodsofgeneratingmdistinctrandomnumbersintherange[0..n-1]我有两种方法在范围[0.n-1]中生 ... [详细]
  • 微信公众号推送模板40036问题
    返回码错误码描述说明40001invalidcredential不合法的调用凭证40002invalidgrant_type不合法的grant_type40003invalidop ... [详细]
  • [转]doc,ppt,xls文件格式转PDF格式http:blog.csdn.netlee353086articledetails7920355确实好用。需要注意的是#import ... [详细]
  • poj 3352 Road Construction ... [详细]
  • 在JavaWeb开发中,文件上传是一个常见的需求。无论是通过表单还是其他方式上传文件,都必须使用POST请求。前端部分通常采用HTML表单来实现文件选择和提交功能。后端则利用Apache Commons FileUpload库来处理上传的文件,该库提供了强大的文件解析和存储能力,能够高效地处理各种文件类型。此外,为了提高系统的安全性和稳定性,还需要对上传文件的大小、格式等进行严格的校验和限制。 ... [详细]
  • 在《Cocos2d-x学习笔记:基础概念解析与内存管理机制深入探讨》中,详细介绍了Cocos2d-x的基础概念,并深入分析了其内存管理机制。特别是针对Boost库引入的智能指针管理方法进行了详细的讲解,例如在处理鱼的运动过程中,可以通过编写自定义函数来动态计算角度变化,利用CallFunc回调机制实现高效的游戏逻辑控制。此外,文章还探讨了如何通过智能指针优化资源管理和避免内存泄漏,为开发者提供了实用的编程技巧和最佳实践。 ... [详细]
  • 在对WordPress Duplicator插件0.4.4版本的安全评估中,发现其存在跨站脚本(XSS)攻击漏洞。此漏洞可能被利用进行恶意操作,建议用户及时更新至最新版本以确保系统安全。测试方法仅限于安全研究和教学目的,使用时需自行承担风险。漏洞编号:HTB23162。 ... [详细]
  • 在C++程序中,文档A的每一行包含一个结构体数据,其中某些字段可能包含不同数量的数字。需要将这些结构体数据逐行读取并存储到向量中,随后不仅在控制台上显示,还要输出到新创建的文档B中。希望得到指导,感谢! ... [详细]
  • 在优化Nginx与PHP的高效配置过程中,许多教程提供的配置方法存在诸多问题或不良实践。本文将深入探讨这些常见错误,并详细介绍如何正确配置Nginx和PHP,以实现更高的性能和稳定性。我们将从Nginx配置文件的基本指令入手,逐步解析每个关键参数的最优设置,帮助读者理解其背后的原理和实际应用效果。 ... [详细]
  • 在Android平台中,播放音频的采样率通常固定为44.1kHz,而录音的采样率则固定为8kHz。为了确保音频设备的正常工作,底层驱动必须预先设定这些固定的采样率。当上层应用提供的采样率与这些预设值不匹配时,需要通过重采样(resample)技术来调整采样率,以保证音频数据的正确处理和传输。本文将详细探讨FFMpeg在音频处理中的基础理论及重采样技术的应用。 ... [详细]
  • 在Linux系统中,网络配置是至关重要的任务之一。本文详细解析了Firewalld和Netfilter机制,并探讨了iptables的应用。通过使用`ip addr show`命令来查看网卡IP地址(需要安装`iproute`包),当网卡未分配IP地址或处于关闭状态时,可以通过`ip link set`命令进行配置和激活。此外,文章还介绍了如何利用Firewalld和iptables实现网络流量控制和安全策略管理,为系统管理员提供了实用的操作指南。 ... [详细]
author-avatar
黄思悦-XHNZ_314
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有