优化两个大路径的Firebase数据结构 [英] Optimizing Firebase data structure for two large paths

查看:142
本文介绍了优化两个大路径的Firebase数据结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想我已经把自己的脑袋包装在反规范化中,作为一个主要的优化方法,将数据存储在Firebase中,如这一个,在这个博客文章,但我陷在一个小细节。

假设我在我的域中有两件事,用户和帖子在博客文章我提到过,我可能有20,000个用户和20,000个帖子。因为我像非常好的孩子那样去规范化所有的东西, root / users / posts 就像 root / posts 一样存在。 root / users / posts 有一组post键值为true,这样我就可以得到用户的所有post键。

 用户:{
userid:{
name:'johnny'
posts:{
-Kofijdjdlehh:true,
-Kd9isjwkjfdj:true
}
}
}

文章:{
-Kofijdjdlehh: {
title:'My hot post',
content:'This was my content',
postedOn:'3987298737'
},
-Kd9isjwkjfdj:{
title:'My hot post',
content:'This is my content',
postedOn:'3987298737'
}
}

现在,我想列出用户发布的所有帖子的标题。我不想加载所有20,000个职位为了得到标题。我只能想到以下选项:
$ b


  1. 查询 root / posts 路径以某种方式使用 root / users / posts 路径中设置为 true 的键的子集(如果这是可能的,我还没有弄清楚)

  2. code>,这样路径中的每个条目的标题都被复制成这样:

    posts:{
    -Kofijdjdlehh :
    $




    $ posts:{
    -Kofijdjdlehh:{
    title:'This is my content'
    }
    }



    这似乎是合理的,但我还没有看到一个这样做的例子,所以我担心这是一些反模式。


  3. 我还没有找到另一种方法

感谢您可能拥有的任何指针或文档可能错过了这个用例。

解决方案

要么是有效的解决方案。 #1会更多的工作谁读数据,而#2会更多的工作,当数据被保存。同样,对于#2,您必须处理帖子标题的更新,但使用新的多路径更新将会非常容易。

要实现#1,你需要做两个查询。这是一个真正的基本解决方案,只处理添加帖子。它侦听添加到用户的帖子,然后将侦听器连接到每个帖子的标题。

  var usersPosts = {} ; ('child_added',function(idSnap){
var id = idSnap.key(); $ b $ ref.child('users')。child(userId).child('posts')。 ('value',function(titleSnap){
usersPosts [id] = titleSnap。)。
$ b ref.child('posts')。 val();
});

});

对于第三种解决方案,您可以使用 firebase-util ,它自动处理上述场景等等。这段代码基本上和上面的代码一样,除了它带给你一个ref的奖金。

 新的Firebase.util.NormalizedCollection(
[ref.child('users')。child(userId).child(posts),posts],
[ref.child(posts ),post]
).select(
{
key:posts。$ value,
别名:x
},
{
key:post.title,
别名:title
}
).ref();

请注意, x 值将始终为真正。有必要选择它,因为firebase-util要求你从每个路径中至少选择一个字段。

I think I've wrapped my head around denormalization as a primary method of optimization when storing data in Firebase as mentioned in question like this one and in this blog post but I'm getting stuck on one small detail.

Assuming I have two things in my domain, users and posts as in the blog article I mentioned, I might have 20,000 users and 20,000 posts. Because I denormalized everything like a good boy, root/users/posts exists as does root/posts. root/users/posts has a set of post keys with a value of true so that I can get all post keys for a user.

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'
    }
}

Now, I want to list the title of all posts a user has posted. I don't want to load all 20,000 posts in order to get the title. I can only think of the following options:

  1. Query the root/posts path in some way using the subset of keys that are set to true in the root/users/posts path (if this is possible, I haven't figured out how)

  2. Store the title in the root/users/posts so that each entry in that path has the title duplicated looking like this:

    posts: { -Kofijdjdlehh: true }

    becomes

    posts: { -Kofijdjdlehh: { title: 'This was my content' } }

    This seems reasonable, but I haven't seen a single example of doing this, so I'm concerned that it's some anti-pattern.

  3. Another way I haven't been able to find

I appreciate any pointers you might have or documentation I might have missed on this use case.

解决方案

Either are valid solutions. #1 would be more work for whoever is reading the data, while #2 would be more work when data is saved. Also for #2, you'd have to handle updates to post's titles, though this would be pretty easy with the new multi-path updates.

To implement #1, you'd have you essentially do two queries. Here's a really basic solution which only handles adding posts. It listens for posts being added to the user, and then hooks up a listener to each post's title.

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();
    });

});

For a third solution, you could use firebase-util, which automagically handles the above scenario and more. This code would essentially do the same as the code above, except it comes with the bonus of giving you one ref to handle.

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();

Note that the x value will always be true. It's necessary to select that because firebase-util requires you to select at least one field from each path.

这篇关于优化两个大路径的Firebase数据结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆