我在工作中讨论了1到N关系中的双向引用。 According to this post in MongoDB blog,你可以做到。我们根本不需要原子更新,所以没问题。按照本文中的示例,在我们的示例中,您只能创建或删除任务,但不能更改任务所有者。
我的论点是双向引用可能更有效地从双方获取数据,因为我们需要在程序的不同部分更频繁地显示所有者的任务,而不仅仅是任务。我的同事说没有效率提升,数据重复是不值得的。
您对这种方法的效率有任何信息吗?
答案 0 :(得分:0)
当我们减少写入次数和读取次数时,对数据进行反规范化和存储会有所帮助。这里的效率取决于数据的检索方式。如果我们从集合中检索数据需要双向引用,如果我们已经拥有它,那么肯定会提高查询效率。
学生收藏
{ _id:1, name: "Joseph", courses:[1, 3, 4]}
{ _id:2, name: "Mary", courses:[1, 3]}
{ _id:3, name: "Catherine", courses:[1, 2, 4]}
{ _id:4, name: "Robert", courses:[2, 4]}
课程集
{ _id:1, name: "Math101", students: [1, 2, 3]}
{ _id:2, name: "Science101", students: [3, 4]}
{ _id:3, name: "History101", students: [1, 2]}
{ _id:4, name: "Astronomy101", students: [1, 3, 4]}
考虑上面的学生和课程示例,这里完成了两种方式的参考,学生系列中的课程数组为我们提供了学生学习的不同课程。同样,Courses系列中的Students数组为我们提供了正在学习相应课程的学生。
如果我们要列出正在学习Math101的学生,那么查询将是
db.courses.aggregate([{$match: {name:"Math101"}},
{$unwind:"$students"},
{$lookup:{from:"students",
localField:"students",
foreignField:"_id",
as:"result"}}])
汇总管道中的$match,$unwind,$lookup用于实现结果。 $ match减少数据(最好在聚合管道的开头使用此运算符),$ unwind来展开Courses集合中的students数组,$ lookup查看Students集合并获取学生详细信息< / p>
在我们的样本集合上执行上述聚合查询后的结果是
{
"_id" : 1,
"name" : "Math101",
"students" : 1,
"result" : [
{
"_id" : 1,
"name" : "Joseph",
"courses" : [
1,
3,
4
]
}
]
}
{
"_id" : 1,
"name" : "Math101",
"students" : 2,
"result" : [
{
"_id" : 2,
"name" : "Mary",
"courses" : [
1,
3
]
}
]
}
{
"_id" : 1,
"name" : "Math101",
"students" : 3,
"result" : [
{
"_id" : 3,
"name" : "Catherine",
"courses" : [
1,
2,
4
]
}
]
}
双向引用的效率完全基于我们检索的内容,因此设计的架构与预期结果紧密相符。