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

Gre*_*reg 6 denormalization nosql angularjs firebase angularfire

好吧我开始使用Firebase.我读过这个:https://www.firebase.com/docs/data-structure.html我读过这个:https://www.firebase.com/blog/2013-04-12-denormalizing-是-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"
  }
}
Run Code Online (Sandbox Code Playgroud)

作者列表和帖子列表.首先,我想让作者在哪里userUid等于我当前的用户uid.然后我想获得authorId提供给查询的帖子.

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

Kat*_*ato 5

Firebase是NoSQL数据存储.它是一个JSON层次结构,并且没有传统意义上的SQL查询(这些查询与闪电般快速的实时操作不兼容;它们往往是缓慢而昂贵的).有一些地图缩减样式功能的计划(合并视图和工具来协助这个),但目前你的主要武器是适当的数据结构.

首先,让我们解决树层次结构与非规范化数据的问题.这里有一些你应该反规范化的东西:

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

这里有一些反正规化可能没有意义的事情:

  • 您总是获取的数据并且从不迭代(如果您总是.child(...).on('value', ...)用来获取某些记录并且您在该记录中显示所有内容,从不引用父列表,则没有理由优化迭代)
  • 列出短于一百个左右的记录,你总是作为一个整体(例如,用户所属的组列表可能总是被该用户获取,平均5-10个项目;可能没有理由将它分开)

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

var userId = 123;
new Firebase('https://INSTANCE.firebaseio.com/users/'+userId);
Run Code Online (Sandbox Code Playgroud)

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

/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());
   });
});
Run Code Online (Sandbox Code Playgroud)

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();
});
Run Code Online (Sandbox Code Playgroud)

或者只是按用户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());
});
Run Code Online (Sandbox Code Playgroud)