AngularFire - 如何查询非规范化数据?

Posted

技术标签:

【中文标题】AngularFire - 如何查询非规范化数据?【英文标题】:AngularFire - How do I query denormalised data? 【发布时间】:2014-04-19 00:31:49 【问题描述】:

好的,我刚开始使用 Firebase。我读过这个:https://www.firebase.com/docs/data-structure.html 我读过这个:https://www.firebase.com/blog/2013-04-12-denormalizing-is-normal.html

所以我很困惑,因为一个似乎与另一个相矛盾。您可以分层构建数据,但如果您希望它具有可扩展性,则不要这样做。然而,这不是真正的问题。

我的博客引擎结构如下(如有错误请纠正我):

"authors" : 
  "-JHvwkE8jHuhevZYrj3O" : 
    "userUid" : "simplelogin:7",
    "email"   : "myemail@domain.com"
  
,
"posts" : 
  "-JHvwkJ3ZOZAnTenIQFy" : 
    "state" : "draft",
    "body" : "This is my first post",
    "title" : "My first blog",
    "authorId" : "-JHvwkE8jHuhevZYrj3O"
  

作者列表和帖子列表。首先,我想获得userUid 等于我当前用户的uid 的作者。然后我想获取authorId 是提供给查询的帖子。

但我不知道该怎么做。任何帮助,将不胜感激!如果有什么不同,我会使用 AngularFire。

【问题讨论】:

【参考方案1】:

Firebase 是一个 NoSQL 数据存储。它是一个 JSON 层次结构,没有传统意义上的 SQL 查询(这些查询与闪电般快速的实时操作并不真正兼容;它们往往速度慢且成本高)。有一些地图缩减样式功能的计划(合并视图和工具来帮助实现这一点),但您目前的主要武器是正确的数据结构。

首先,让我们处理树层次结构与非规范化数据。这里有一些你应该去规范化的东西:

您希望能够快速迭代的列表(用户名列表,无需下载用户曾经写过的每条消息或有关用户的所有其他元信息) 您查看部分的大型数据集,例如用户所属的房间/组列表(您应该能够获取给定用户的房间列表,而无需下载系统中的所有组/房间,因此把索引放在一个地方,主人房数据放在另一个地方) 任何超过 1,000 条记录的东西(保持精简以提高速度) 路径下的子项包含 1..n(即可能无限)记录(例如聊天室元数据中的聊天消息,这样您就可以获取有关聊天室的信息而无需抓取所有消息)

以下是一些非规范化可能没有意义的事情:

您始终获取全部数据且从不迭代的数据(如果您始终使用 .child(...).on('value', ...) 获取某些记录并显示该记录中的所有内容,从不引用父列表,则没有理由针对可迭代性进行优化) 列表少于一百条左右的记录,你总是作为一个整体(例如,用户所属的组列表可能总是与该用户一起获取,平均 5-10 项;可能没有理由将其分开)

获取作者就像在 URL 中添加 id 一样简单:

var userId = 123;
new Firebase('https://INSTANCE.firebaseio.com/users/'+userId);

要获取属于某个用户的帖子列表,请维护该用户帖子的索引:

/posts/$post_id/...
/my_posts/$user_id/$post_id/true

var fb = new Firebase('https://INSTANCE.firebaseio.com');
fb.child('/my_posts/'+userId).on('child_added', function(indexSnap) 
   fb.child('posts/'+indexSnap.name()).once('value', function(dataSnap) 
       console.log('fetched post', indexSnap.name(), dataSnap.val());
   );
);

Firebase.util 之类的工具可以帮助规范化已拆分存储的数据,直到 Firebase 的视图和高级查询工具发布:

/posts/$post_id/...
/my_posts/$user_id/$post_id/true

var fb = new Firebase('https://INSTANCE.firebaseio.com');
var ref = Firebase.util.intersection( fb.child('my_posts/'+userId), fb.child('posts') );
ref.on('child_added', function(snap) 
   console.log('fetched post', snap.name(), snap.val();
);

或者简单地按用户 ID 存储帖子(取决于您以后如何获取该数据的用例):

/posts/$user_id/$post_id/...

new Firebase('https://INSTANCE.firebaseio.com/posts/'+userId).on('child_added', function(snap) 
   console.log('fetched post', snap.name(), snap.val());
);

【讨论】:

这对我来说很快就变得更有意义了。我认为是因为它将它应用到我自己制造的情况中。谢谢你的解释! 我的荣幸!我还使用 Firebase.util 添加了一个示例。 这是一个很好的答案,但我来到这里是因为我正在寻找 AngularFire 语法来查询以与第一个示例相同的方式保存的数据 - /posts/$ post_id/ + /my_posts/$user_id/$post_id/true。你也可以提供吗? @H.Wolper 提出一个新问题。我很乐意提供帮助。

以上是关于AngularFire - 如何查询非规范化数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何格式化和显示从 AngularFire 返回的 Firestore 数据?

使用 Firestore/Angularfire2 或 Firestore SDK 查询集合中的内部对象 ID

ActiveRecord - 非规范化案例研究

AngularFire2:实时数据库:如何获取键和值

如何在文档 + angularfire2 + angular5 中添加集合

性能调优 SQL - 如何?