【问题标题】:Firebase data structure for realtime snapshot and retrospective analysis用于实时快照和回顾分析的 Firebase 数据结构
【发布时间】:2016-07-25 09:38:34
【问题描述】:

我正在尝试为以下场景确定构建数据的最佳方式。我在一个有 50 个相互连接的田地的农场里养了 10000 只羊。当每只羊进入和离开田地时,我都会跟踪它们。我希望能够:

  • 回顾性分析每只羊在给定时间段内的运动
  • 我还想分析每个字段在一段时间内的使用情况
  • 立即知道任何给定的羊目前在哪个领域
  • 立即知道给定领域有哪些羊

我已经阅读了 documentation 关于去规范化数据的内容,我很感激我可以使用查询等做任何事情。

我的问题是:我应该像这样将进入/退出数据复制到羊和场节点吗?:

{
    sightings: {
        uniqueSheepId: {
            FirebaseAutoId: {
                type: enter
                fieldId: uniqueFieldId
                timestamp: xxxxxxxx.xxxxx
            }
        }
    }
}

{
    sightings: {
        uniqueFieldId: {
            FirebaseAutoId: {
                type: enter
                sheepId: uniqueSheepId
                timestamp: xxxxxxxx.xxxxx
            }
        }
    }
}

这似乎是获取任何给定领域中有多少只羊的实时快照的好方法。它还使我们能够轻松地看到一只羊现在在哪里以及它在哪里,而无需进行任何查询。显然,数据集的大小将比我使用查询增长两倍,但是获取数据的简单性是否超过了存储数据的成本?

我已经看到(并理解)SO 上的聊天室/成员示例,但我认为我希望从绵羊和现场的角度回顾性分析成员/使用情况,这使得我的问题与这些答案略有不同。任何建议都会很棒。

【问题讨论】:

    标签: firebase firebase-realtime-database nosql


    【解决方案1】:

    您当前的数据结构就足够了:

    sightings: {
        uniqueSheepId: {
            FirebaseAutoId: {
                type: enter
                fieldId: uniqueFieldId
                timestamp: xxxxxxxx.xxxxx
            }
        }
    }
    

    而且你不需要复制。您可以为每个需求创建一个查询。

    但是,我已经多次准备好在 Firebase 中创建更多平坦的树而不是创建更少的深度树。以下推荐的结构会更好一些查询,但对其他查询不太好,但我相信总体会更好,并允许将来添加 fieldssheep 的其他属性.


    因此,为了限制冗余数据,我将设置三种不同的树,sheepfieldssightings

    sheep: {
        uniqueSheepId: {
            currentField: uniqueFieldId,
            sightings: {
                FirebaseAutoId: uniqueSightingsId,
                ...
            }
        }
    }
    

    fields: {
        uniqueFieldId: {
            numberOfSheep: number,
            sightings: {
                FirebaseAutoId: uniqueSightingsId,
                ...
            }
        }
    }
    

    sightings: {
        FirebaseAutoId: {
            type: enter,
            sheepId: uniqueSheepId,
            fieldId: uniqueFieldId,
            timestamp: xxxxxxxx.xxxxx
        }
    }
    

    回顾性分析每只羊在给定时间段内的运动

    可以查询羊的动向:sheep/uniqueSheepId/sightings

    我还想分析每个字段随时间的使用情况

    您可以查询该字段的使用情况:fields/uniqueFieldId/sightings

    立即知道任何给定的羊目前在哪个领域

    您可以查询任何给定羊的字段:sheep/uniqueSheepId/currentField

    立即知道给定领域有哪些绵羊

    在 JavaScript 中你可以这样查询:

    var ref = firebase.database().ref("sheep").orderByChild("currentField").equalTo(uniqueFieldId);
    

    可以使用任何 Firebase 支持的语言进行等效操作。

    所有这些都假设您正在实时正确地更新和推送到数据库

    【讨论】:

    • 谢谢。我理解您的建议,并且可以看到它如何满足我设定的要求。但是,从某种意义上说,它似乎是“相关的”,因为我需要过滤 /sightings 以根据 sheep/uniqueSheepId/sightings 中的孩子检索给定绵羊(或田地)的目击细节。由于我必须进行此查找,因此对于 sheepId == uniqueSheepId 的子项简单地查询 /sightings 并且不费心将引用存储在 /sheep/uniqueSheepId/sightings 节点中,感觉不会那么糟糕。存储参考列表是否更有效?
    • 这都是依赖的。我推荐的一些查询需要来自先前查询的数据。但是您的查询将在更大的树中进行筛选,这可能需要与 2 个较小的查询一样多的时间。我已经编辑了我的问题,请阅读开头。
    • 感谢您的澄清。我认为这是“存储非规范化数据的 $$$ 成本与查询的时间成本”的问题。由于目击数据只写入一次(即从未更新),同时将其写入 2 个地方(绵羊和田地)似乎没有太大问题。对于这个用例,firebase 的 $$$ 成本似乎相当合理。顺便说一句,我肯定会将您的 currentField 和 numberOfSheep “计数器”属性添加到我的数据结构中 - 也感谢您。
    猜你喜欢
    • 2020-04-28
    • 2016-10-18
    • 1970-01-01
    • 2021-01-21
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 2020-08-05
    相关资源
    最近更新 更多