我认为,当我在Firebase中存储数据(例如this one和blog post中提到的数据)时,我已经将非规范化作为优化的主要方法包围了我,但是我在这里卡在一个小细节上。
假设我的域名,用户和帖子中有两件事,就像我提到的blog article那样,我可能有20,000个用户和20,000个帖子。因为我像一个好孩子一样对所有事情进行了规范化,root/users/posts
和root/posts
一样存在。 root/users/posts
有一组值为true的post键,以便我可以获取用户的所有帖子密钥。
users: {
userid: {
name: 'johnny'
posts: {
-Kofijdjdlehh: true,
-Kd9isjwkjfdj: true
}
}
}
posts: {
-Kofijdjdlehh: {
title: 'My hot post',
content: 'this was my content',
postedOn: '3987298737'
},
-Kd9isjwkjfdj: {
title: 'My hot post',
content: 'this was my content',
postedOn: '3987298737'
}
}
现在,我想列出用户发布的所有帖子的标题。我不想加载所有20,000个帖子以获得标题。我只能想到以下几个选项:
使用在root/posts
路径中设置为true
的密钥子集以某种方式查询root/users/posts
路径(如果可行的话,我没有'} t弄清楚如何)
将标题存储在root/users/posts
中,以便该路径中的每个条目都具有重复的标题,如下所示:
posts: {
-Kofijdjdlehh: true
}
变为
posts: {
-Kofijdjdlehh: {
title: 'This was my content'
}
}
这似乎是合理的,但我还没有看到这样做的一个例子,所以我担心它会有一些反模式。
我无法找到的另一种方式
我感谢您可能提供的任何指示或我可能错过的用例。
答案 0 :(得分:3)
两者都是有效的解决方案。 #1对于正在阅读数据的人来说会更有效,而#2在保存数据时会更有效。同样对于#2,您必须处理帖子标题的更新,尽管使用新的multi-path updates会非常容易。
要实施#1,您基本上要做两个查询。这是一个非常基本的解决方案,只处理添加帖子。它会监听添加到用户的帖子,然后将听众连接到每个帖子的标题。
var usersPosts = {};
ref.child('users').child(userId).child('posts').on('child_added', function(idSnap) {
var id = idSnap.key();
ref.child('posts').child(id).child('title').on('value', function(titleSnap) {
usersPosts[id] = titleSnap.val();
});
});
对于第三种解决方案,您可以使用firebase-util,它可以自动处理上述场景等。这段代码基本上和上面的代码一样,除了它带有给你一个ref处理的奖励。
new Firebase.util.NormalizedCollection(
[ref.child('users').child(userId).child("posts"), "posts"],
[ref.child("posts"), "post"]
).select(
{
key: "posts.$value",
alias: "x"
},
{
key: "post.title",
alias: "title"
}
).ref();
请注意,x
值始终为true。选择它是必要的,因为firebase-util要求您从每个路径中选择至少一个字段。