Firebase中的多对多关系

Firebase中的多对多关系,firebase,firebase-realtime-database,angularfire2,nosql,Firebase,Firebase Realtime Database,Angularfire2,Nosql,我有一个Firebase数据库。我有公司和承包商。一个承包商可以为多个公司工作,一个公司可以有多个承包商。这是一种简单的多对多关系。我希望能够回答有关公司和承包商的问题: 给定一家公司,谁是当前的承包商 给定一个承包商,他们为哪些公司工作 在firebase中构建数据的备选方案是什么?在进一步研究之后,我将尝试回答我自己的问题。我已经查看了许多其他帖子,解决多对多问题的一个方法是在公司对象中存储一个ContractWorkey列表,并在每个contractor对象中存储一个CompanyKey列

我有一个Firebase数据库。我有公司和承包商。一个承包商可以为多个公司工作,一个公司可以有多个承包商。这是一种简单的多对多关系。我希望能够回答有关公司和承包商的问题:

  • 给定一家公司,谁是当前的承包商
  • 给定一个承包商,他们为哪些公司工作
    在firebase中构建数据的备选方案是什么?

    在进一步研究之后,我将尝试回答我自己的问题。我已经查看了许多其他帖子,解决多对多问题的一个方法是在公司对象中存储一个ContractWorkey列表,并在每个contractor对象中存储一个CompanyKey列表。下面的例子说明了这一点

    companies : {
      companyKey1 : {
        name : company1
        ...
        contractors : {
          contractorKey1 : true,   
          contractorKey3 : true
        }
      }
      companyKey2 : {
        name : company2
        ...
        contractors : {
          contractorKey2 : true,  
        } 
      }
    }
    contrators : {
      contractorKey1 : {
         name : bill
         ...
         companies : {
            companyKey1 : true
         }
       }
      contractorKey2 : {
         name : steve
         ...
         companies : {
            companyKey1 : true
         }
    
       }
      contractorKey3 : {
         name : jim
         ...
         companies : {
            companyKey2 : true
         }
       }
    }
    
    该组织“运作”的意义在于上述问题可以得到回答。但这种解决方案的一个缺点是,当承包商/公司的任务发生变化时,需要维护两个列表。如果有一种方法可以在单个列表中表示这些信息,那就更好了

    我想我已经想出了一个更好的解决办法。解决方案是除了名为companyAndContractorAssignment的公司和承包商之外,创建第三个列表。本清单的要素将代表单个承包商和公司之间的关系。它的内容将是一对字段,ContractWorkey和companyKey。然后,我们可以删除公司内的承包商名单和承包商内的公司名单。这种替代结构如下所示。请注意,公司对象中没有承包商列表,也没有包含承包商对象的公司列表

    companies : {
      companyKey1 : {
        name : company1
        ...
      }
      companyKey2 : {
        name : company2
        ...
      }
    }
    contrators : {
      contractorKey1 : {
         name : bill
         ...
      }
      contractorKey2 : {
         name : steve
         ...
      }
      contractorKey3 : {
         name : jim
         ...
      }
    }
    companyAndContractorsAssignment : {
      key1 : {
        contractorKey1 : true,
        companyKey1: true,
      }
      key2 : {
        contractorKey3 : true,
        companyKey1: true,
      }
      key3 : {
        contractorKey2 : true,
        companyKey2: true,
      }
    

    这种替代结构允许用户使用orderByChild/equalTo查询company和DcontractorsAssignment来回答问题,以查找承包商的所有公司或公司的所有承包商。现在只有一个列表需要维护。我认为这是满足我需求的最佳解决方案。

    自我回答确实是建模的一种方式。这可能是在关系数据库中对此进行建模的最直接等效方法:

    • 承包商
    • 公司
    • CompanyAndContractorAssignment(多对多连接器表)
    另一种方法是使用4个顶级节点:

    • 承包商
    • 公司
    • 公司承包商
    • 承包公司
    最后两个节点看起来像:

    companyContractors
        companyKey1
            contractorKey1: true
            contractorKey3: true
        companyKey2
            contractorKey2: true
    contractorCompanies
        contractorKey1
            companyKey1: true
        contractorKey2
            companyKey2: true
        contractorKey3
            companyKey1: true
    
    这种双向结构允许您同时查找“公司的承包商”和“承包商的公司”,而无需查询其中任何一个。这肯定会更快,尤其是当您添加承包商和公司时

    这是否对你的应用程序是必要的,取决于你需要的用例、你期望的数据大小等等

    推荐阅读和查看。这一问题也被刊登在一篇文章中

    更新(2017016)
    有人发布了一篇关于从“承包商”和“公司”节点检索实际项目的帖子。您需要一次检索一个,因为Firebase没有与(1,2,3)中id所在的表中的
    SELECT*等效的代码。但是这个操作并不像您想象的那么慢,因为请求是通过单个连接进行管道传输的。请在此处阅读更多相关信息:。

    我认为,如果您使用此方法,可能会在索引方面出现性能问题。Firebase会要求您在orderByChild上执行indexOn,但由于这些是动态键,维护起来可能会变成一场噩梦。您看到过任何性能问题吗?我喜欢作业模型,因为只有一个列表需要维护。我担心维护公司的承包商和承包商公司会变得困难。我认为4节点解决方案更优越。不仅仅是为了性能,我相信在规模上它的性能会更好。我的申请没有太多的承包商。我计划迁移到4节点解决方案…嘿,frank,如果我将contractors密钥存储到公司中,将公司密钥存储到contractors中会怎么样?创建新表是为了提高性能还是为了查看?是否有任何方法可以使用.validation或.write规则来验证这些值……即,承包商不应包含不存在的公司密钥。@AdirZoari:您找到问题的解决方案了吗??