Firebase 中的多对多关系

Posted

技术标签:

【中文标题】Firebase 中的多对多关系【英文标题】:Many to Many relationship in Firebase 【发布时间】:2017-05-22 11:26:44 【问题描述】:

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

    给定一个公司,他们是当前的承包商。 为承包商提供他们为哪些公司工作的公司。

在 firebase 中结构化数据的替代方法是什么?

【问题讨论】:

【参考方案1】:

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

承包商 公司 companyAndContractorsAssignment(多对多连接器表)

另一种方法是使用 4 个***节点:

承包商 公司 公司承包商 承包商公司

最后两个节点如下所示:

companyContractors
    companyKey1
        contractorKey1: true
        contractorKey3: true
    companyKey2
        contractorKey2: true
contractorCompanies
    contractorKey1
        companyKey1: true
    contractorKey2
        companyKey2: true
    contractorKey3
        companyKey1: true

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

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

推荐阅读NoSQL data modeling和查看Firebase for SQL developers。这个问题也出现在episode of the #AskFirebase youtube series。

更新 (2017016)

有人发布了follow-up question that links here,关于从“承包商”和“公司”节点检索实际项目。您需要一次检索那些,因为 Firebase 没有与 SELECT * FROM table WHERE id IN (1,2,3) 等效的内容。但是这个操作并不像你想象的那么慢,因为请求是通过单个连接流水线化的。在此处阅读更多相关信息:Speed up fetching posts for my social network app by using query instead of observing a single event repeatedly。

【讨论】:

嘿,坦率地说,如果我将承包商密钥存储到公司中并将公司密钥存储到承包商中怎么办?创建新表是为了提高性能还是为了查看? 有没有办法使用 .validation 或 .write 规则来验证这些值....即,承包商不应包含不存在的 companyKey。 @AdirZoari:你找到解决问题的方法了吗??【参考方案2】:

经过进一步研究,我将尝试回答我自己的问题。我已经查看了许多其他帖子,多对多问题的一种解决方案是将 ContractorKeys 列表存储在 Company 对象中,并将 CompanyKeys 列表存储在每个承包商对象中。这通过下面的示例进行说明。

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 的公司和承包商之外。此列表的元素将代表单个承包商和公司之间的关系。它的内容将是一对字段,contractorKey 和 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,
  

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

【讨论】:

我认为如果你这样做,你可能会在索引方面遇到性能问题。 Firebase 会要求您对 orderByChild 执行 indexOn,但由于这些是动态键,因此维护起来可能会变成一场噩梦。 您是否发现任何性能问题?我喜欢分配模型,因为需要维护一个列表。恐怕很难维护 companyContractors 和contractorCompanies。 我认为 4 节点解决方案更胜一筹。不仅是为了性能,而且我敢肯定它在规模上表现得更好。我的应用程序没有很多承包商。我有计划迁移到 4 节点解决方案...

以上是关于Firebase 中的多对多关系的主要内容,如果未能解决你的问题,请参考以下文章

Access中的多对多关系来自单个表

SQL Server Analysis Services 中的多对多关系;第二个多对多关系不起作用

Hibernate-ORM:12.Hibernate中的多对多关联关系

如何处理mongodb中的多对多关系

sqlalchemy中的多对多自引用关系

教义中的多对多关系