【问题标题】:Optimizing Firebase data structure for two large paths为两条大路径优化 Firebase 数据结构
【发布时间】:2015-10-13 07:37:25
【问题描述】:

我认为我已经将非规范化作为一种​​主要的优化方法,将数据存储在 Firebase 中,如this one 和此blog post 等问题中提到的,但我陷入了一个小细节。

假设我的域中有两个东西,用户和帖子,如我提到的blog article,我可能有 20,000 个用户和 20,000 个帖子。因为我像一个好孩子一样对一切进行了非规范化,root/users/postsroot/posts 一样存在。 root/users/posts 有一组值为 true 的 post 键,因此我可以获得用户的所有 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 个帖子。我只能想到以下选项:

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

  2. 将标题存储在root/users/posts 中,以便该路径中的每个条目都具有重复的标题,如下所示:

    posts: { -Kofijdjdlehh: true }

    变成

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

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

  3. 我找不到的另一种方式

感谢您提供的关于此用例的任何建议或我可能遗漏的文档。

【问题讨论】:

    标签: firebase


    【解决方案1】:

    两者都是有效的解决方案。 #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 值将始终为真。必须选择它,因为 firebase-util 要求您从每个路径中至少选择一个字段。

    【讨论】:

    • 这些似乎假设我已经连接并等待数据更改。当用户连接并且我需要一次查询他们历史上添加的给定用户的所有帖子标题时怎么办?我能否以某种方式从posts 路径中获取与user/posts 路径中的任何ID 匹配的帖子子集?
    • 不,我写出的两个解决方案并不假设您已连接并等待数据更改。他们检索您要求的内容并且 将继续侦听更多数据。 child_added 为每个新旧孩子调用。 value 首先为现有值调用,然后在每次更改时调用。
    • 啊,对对对。对我来说,这是一个很难保留的范式。好的,我认为这已经开始深入人心了。循环数据访问在我身上训练有素,所以重新学习这部分内容很困难。感谢您的帮助。
    • @AnidMonsur 你能提供 android (java) 代码来实现#1吗?谢谢!
    猜你喜欢
    • 2016-05-08
    • 1970-01-01
    • 2011-11-30
    • 2021-02-24
    • 2019-09-23
    • 2019-04-01
    • 2020-11-30
    • 1970-01-01
    • 2014-06-06
    相关资源
    最近更新 更多