热门标签 | 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到使用非结构化时,我遇到了同样的问题,所以我希望有所帮助!


推荐阅读
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • vue使用
    关键词: ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • 本文介绍了如何使用PHP向系统日历中添加事件的方法,通过使用PHP技术可以实现自动添加事件的功能,从而实现全局通知系统和迅速记录工具的自动化。同时还提到了系统exchange自带的日历具有同步感的特点,以及使用web技术实现自动添加事件的优势。 ... [详细]
  • 电话号码的字母组合解题思路和代码示例
    本文介绍了力扣题目《电话号码的字母组合》的解题思路和代码示例。通过使用哈希表和递归求解的方法,可以将给定的电话号码转换为对应的字母组合。详细的解题思路和代码示例可以帮助读者更好地理解和实现该题目。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
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社区 版权所有