Firebase 中的多对多关系
Many to Many relationship in Firebase
我有一个 Firebase 数据库。我有公司和承包商。一个承包商可以为多个公司工作,一个公司可以有多个承包商。这是一个简单的多对多关系。我希望能够回答有关公司和承包商的问题:
- 给定一个公司,谁是当前的承包商。
- 给定承包商,他们为哪些公司工作。
在 Firebase 中构建数据的替代方案是什么?
经过进一步研究,我将尝试回答我自己的问题。我已经查看了许多其他帖子,解决多对多问题的一个方法是在公司对象中存储一个 ContractorKeys 列表,并在每个承包商对象中存储一个 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
}
}
}
这个组织"works"在某种意义上可以回答上述问题。但此解决方案的缺点是,当 Contractor/Company 分配发生变化时,需要维护两个列表。如果有一种方法可以在单个列表中表示此信息,那就更好了。
我想我想出了一个更好的解决方案。解决方案是创建第三个列表,除了名为 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 查询来回答问题,以查找承包商的所有公司或公司的所有承包商。现在只需要维护一个列表。我认为这是满足我要求的最佳解决方案。
自我回答确实是对此进行建模的一种方式。这可能是您在关系数据库中建模的最直接的等价物:
- 承包商
- 公司
- companyAndContractorsAssignment(多对多连接器table)
另一种方法是使用 4 个顶级节点:
- 承包商
- 公司
- 公司承包商
- 承包商公司
最后两个节点看起来像:
companyContractors
companyKey1
contractorKey1: true
contractorKey3: true
companyKey2
contractorKey2: true
contractorCompanies
contractorKey1
companyKey1: true
contractorKey2
companyKey2: true
contractorKey3
companyKey1: true
这种双向结构允许您同时查找 "contractors for a company" 和 "companies for a contractor",而无需对其中任何一个进行查询。这肯定会更快,尤其是当您添加承包商和公司时。
您的应用是否需要这取决于您需要的用例、您期望的数据大小等等。
推荐阅读NoSQL data modeling and viewing Firebase for SQL developers. This question was also featured in an episode of the #AskFirebase youtube series.
更新 (2017016)
有人发布了 follow-up question that links here about retrieving the actual items from the "contractors" and "companies" nodes. You will need to retrieve those one at a time, since Firebase doesn't have an equivalent to SELECT * FROM table WHERE id IN (1,2,3)
. But this operation is not as slow as you may think, because the requests are pipelined over a single connection. Read more about that here: 。
我有一个 Firebase 数据库。我有公司和承包商。一个承包商可以为多个公司工作,一个公司可以有多个承包商。这是一个简单的多对多关系。我希望能够回答有关公司和承包商的问题:
- 给定一个公司,谁是当前的承包商。
- 给定承包商,他们为哪些公司工作。
在 Firebase 中构建数据的替代方案是什么?
经过进一步研究,我将尝试回答我自己的问题。我已经查看了许多其他帖子,解决多对多问题的一个方法是在公司对象中存储一个 ContractorKeys 列表,并在每个承包商对象中存储一个 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
}
}
}
这个组织"works"在某种意义上可以回答上述问题。但此解决方案的缺点是,当 Contractor/Company 分配发生变化时,需要维护两个列表。如果有一种方法可以在单个列表中表示此信息,那就更好了。
我想我想出了一个更好的解决方案。解决方案是创建第三个列表,除了名为 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 查询来回答问题,以查找承包商的所有公司或公司的所有承包商。现在只需要维护一个列表。我认为这是满足我要求的最佳解决方案。
自我回答确实是对此进行建模的一种方式。这可能是您在关系数据库中建模的最直接的等价物:
- 承包商
- 公司
- companyAndContractorsAssignment(多对多连接器table)
另一种方法是使用 4 个顶级节点:
- 承包商
- 公司
- 公司承包商
- 承包商公司
最后两个节点看起来像:
companyContractors
companyKey1
contractorKey1: true
contractorKey3: true
companyKey2
contractorKey2: true
contractorCompanies
contractorKey1
companyKey1: true
contractorKey2
companyKey2: true
contractorKey3
companyKey1: true
这种双向结构允许您同时查找 "contractors for a company" 和 "companies for a contractor",而无需对其中任何一个进行查询。这肯定会更快,尤其是当您添加承包商和公司时。
您的应用是否需要这取决于您需要的用例、您期望的数据大小等等。
推荐阅读NoSQL data modeling and viewing Firebase for SQL developers. This question was also featured in an episode of the #AskFirebase youtube series.
更新 (2017016)
有人发布了 follow-up question that links here about retrieving the actual items from the "contractors" and "companies" nodes. You will need to retrieve those one at a time, since Firebase doesn't have an equivalent to SELECT * FROM table WHERE id IN (1,2,3)
. But this operation is not as slow as you may think, because the requests are pipelined over a single connection. Read more about that here: