【问题标题】:One To Many Relationship In FirebaseFirebase 中的一对多关系
【发布时间】:2016-07-28 16:23:35
【问题描述】:

我有一个 Firebase 数据库。我有 Job 对象和 Item 对象。每个 Job 可以包含许多 Item,并且一个 Item 必须包含在一个 Job 中(简单的一对多)。我目前的数据库结构是 Item 和 Job 都是 firebase 中的顶级列表,每个 Item 都包含它所属的 jobKey。只要我知道作业密钥,这使我可以找到作业中的所有项目。用于查找项目的 firebase 代码需要一个查询,其中包括项目中的 jobKey 和一个“orderBy”。因此很容易检索作业的所有项目。但是,我还想根据项目中的附加数据对项目进行排序和过滤。但是由于单个“orderBy”的firebase限制,我无法使用firebase完成第二级过滤。这是我的挑战。我目前数据的结构如下图所示。

+--jobs
  |
  +-- jobKey1
  |  |
  |  +-- <jobdata1> ..
  |  
  +-- jobKey2
     |
     +-- <jobdata2>..

+--items
  |
  +-- itemKey1
  |  |
  |  +-- jobKey : jobKey2  // this item belongs to job2
  |  |
  |  +-- <the rest of item1 data
  |  
  +-- itemKey2
  |  |
  |  +-- jobKey : jobKey2  // this item belongs to job2
  |  |
  |  +-- <the rest of item2 data
  |  
  +-- itemKey3
  |  |
  |  +-- jobKey : jobKey1  // this item belongs to job1
  |  |
  |  +-- <the rest of item3 data
  |  
  +-- itemKey4
     |
     +-- jobKey : jobKey1  // this item belongs to job1
     |
     +-- <the rest of item4 data

如前所述,我希望能够检索作业的所有项目,然后按项目中的各个字段对项目进行排序和过滤。鉴于上面的结构,这样做的唯一方法(我看到)是使用 firebase 查询来检索项目,然后使用组件中的逻辑(我正在使用 angular2)将所有项目缓存到某种集合中根据缓存的数据进行排序和过滤。这不是很令人满意,必须有更好的方法。有哪些合理的替代方案?

【问题讨论】:

    标签: firebase firebase-realtime-database angularfire2


    【解决方案1】:

    我想出了解决办法。

    另一种结构化数据的方法是将项目列表直接嵌套在作业中。如下图所示。这允许使用 firebase 查询在项目数据中排序和过滤。这似乎是一个很好的解决方案,但它具有扩展缺陷。

       +--jobs
          |
          +-- jobKey1
          |  |
          |  +-- <jobdata> ..
          |  |
          |  +-- items
          |     |
          |     +-- itemKey3
          |     |  |
          |     |  +-- <the rest of item3 data>
          |     | 
          |     +-- itemKey4
          |        |
          |        +-- <the rest of item4 data> 
          |  
          +-- jobKey2
             |
             +-- <jobdata>..
             |
             +-- items
                |
                +-- itemKey1
                |  |
                |  +-- <the rest of item1 data>
                | 
                +-- itemKey2
                   |
                   +-- <the rest of item2 data> 
    

    这个解决方案的一个缺点是,如果项目列表很大,它的扩展性就不是很好,因为每次读取 Job 都会读取所有项目。就我而言,当我阅读 Job 对象时,我不想阅读整个项目列表,而是想创建项目列表的引用并在项目列表上使用 firebase 查询/过滤功能。因此,将项目列表放在 Job 中确实没有直接的好处。在我的应用程序中,实际限制是数百个项目。因此,即使该解决方案可能适用于我的应用程序,也必须有一个更好、更具可扩展性的解决方案。

    更好的解决方案。

    经过进一步考虑,这个问题的最佳解决方案是创建特定于作业但不包含在 Job 对象中的 Item 列表,这样在读取 Job 时,不必读取整个列表.我们还保留了根据数据对项目列表中的数据进行排序/过滤的能力。这种结构如下图所示。每个作业的 ItemLists 保存在路径“itemlists//items”

    +--jobs
       |
       +-- jobKey1
       |  |
       |  +-- <jobdata1> ..
       |  
       +-- jobKey2
          |
          +-- <jobdata2>..
    
     +--itemlists
       |
       +-- jobKey1    // items list for job1   
       |  |
       |  +--items
       |    |
       |    +-- itemKey3
       |    |  |
       |    |  +-- <the rest of item3 data
       |    |  
       |    +-- itemKey4
       |    |  |
       |    |  +-- <the rest of item4 data
       |    
       +-- jobKey2    // items list for job2   
          |
          +--items
            |
            +-- itemKey1
            |  |
            |  +-- <the rest of item1 data
            |  
            +-- itemKey2
               |
               +-- <the rest of item2 data
    

    【讨论】:

    • 谢谢!这是一个有用的帖子。如果你必须列出所有工作的所有项目,你会怎么做?我问是因为我有类似的问题。
    • 我在想您可以创建一个包含所有项目数据的新项目列表,并修改作业项目列表以引用数据而不是存储数据。但这意味着您不能按工作项目列表上的数据进行过滤。也许您可以创建一个新的项目列表,其中包含所有项目的键。但是您将无法过滤它。 firebase 架构的关键是创建可过滤列表。但是可过滤列表需要列表中的可过滤数据。
    • 这是我最初的想法,但这意味着如果一个工作有 25 个项目,我必须每次使用工作数据中的项目键查询项目列表 25 次以获取数据。那是对的吗?使用您最后提到的方法,如果我还想查询所有项目并且我是管理员,我可以获取作业节点并获取所有项目,对吗?
    • 我认为您的正确答案将取决于项目的基数以及您是否要过滤以及在哪里过滤。如果您想要所有项目的 Firebase 可过滤/可排序列表,您别无选择,只能拥有所有项目的列表以及数据。在我的应用程序中,我需要对每个作业的项目进行过滤/排序。没有项目数据重复。无法对每个作业和全局项目列表进行过滤/排序(使用 firebase)。
    • 好的!谢谢你为我清理了一些东西。我现在对如何构建数据有了更好的理解。此外,由于 firebase 库中的原子写入功能,非规范化是可以的。你的帖子帮了大忙!再次感谢!
    猜你喜欢
    • 2017-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-19
    • 1970-01-01
    • 2018-06-15
    • 2017-03-16
    • 2018-09-27
    相关资源
    最近更新 更多