一尘不染

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

angularjs

好的,我刚开始使用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"
  }
}

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

但是我不知道该怎么做。任何帮助,将不胜感激!如果这有所作为,我正在使用AngularFire。


阅读 229

收藏
2020-07-04

共1个答案

一尘不染

Firebase是NoSQL数据存储。这是一个JSON层次结构,没有传统意义上的SQL查询(这些查询与快如闪电的实时操作并不真正兼容;它们往往很慢且昂贵)。已经计划了一些地图精简样式功能(合并的视图和工具来辅助此功能),但是目前您的主要武器是适当的数据结构。

首先,让我们解决树层次结构与非规范化数据之间的关系。您应该对以下几项进行非规范化:

  • 想要快速迭代的列表(无需下载用户曾经写过的每条消息或有关该用户的所有其他元信息的用户名列表)
  • 查看部分数据的大数据集,例如用户所属的房间/组的列表(您应该能够为给定的用户获取房间的列表,而无需下载系统中的所有组/房间,因此请放置索引一个地方,母室数据在其他地方)
  • 记录超过1000条的内容(保持速度)
  • 包含1..n(即,可能是无限个)记录的路径下的子对象(例如,来自聊天室元数据的聊天消息,这样您就可以获取有关聊天室的信息而无需获取所有消息)

以下是一些可能无法正常化的事情:

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

提取作者就像将id添加到URL一样简单:

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的视图和高级查询utils:

/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());
});
2020-07-04