我将字符串与字符串的所有者(每个字符串的一个或多个所有者)一起存储在数据库中。
我一直在使用MySQL,这是一个传统的关系数据库。在这种情况下,我会将字符串与唯一ID一起存储在一个表中,然后将字符串的唯一ID与所有者(作为多个记录)一起存储在第二个表中。
然后我可以使用SQL Join来获取所有者的字符串。
我现在正在使用MongoDB开发一个项目,我的工作与上面相同。
使用NoSQL数据库时,这会被认为是错误的方法吗?在使用NoSQL时,我不应该考虑“关系”吗?
我可以想到在MongoDB中实现相同的另一种方法是将它存储起来:
{
"string": "foobar",
"owners": [
"owner1",
"owner2",
"owner3"
]
}
但是,在这种情况下,我不确定如何搜索“owner1拥有的所有字符串”。
答案 0 :(得分:6)
使用NoSQL数据库时,这会被认为是错误的方法吗?在使用NoSQL时,我不应该考虑“关系”吗?
关于嵌入的情况有很多问题,而且归结为很少。
如果你想嵌入,这里没有提到的某些事情需要考虑:
video
无法嵌入user
)。如果是这种情况,将冗余数据从相关行复制到子文档时可能会出现问题,尤其是在更新冗余数据时。显示结果始终是是否嵌入的关键决定因素。如果需要对大量行(例如1000)进行分页,则需要在常规查询或聚合框架中使用$slice
运算符。在1000我承认它可能非常快,但迟早内存操作将变得比正常查询慢(事实上它总是应该)。
如果您需要复杂的排序和显示子文档,您可能希望将它们拆分出来,而是具有以下文档结构:
{
"string": "foobar",
"owners": [
ObjectId(),
ObjectId(),
ObjectId()
]
}
我认为,对于您的数据,这实际上可能是一个更高效的结构,因为owner
听起来像user
集合中的users
行。
您可以只引用他们的_id
,而不是使用可能更改的用户数据填充子文档。这非常简单,因为你可以嵌入这种关系,但同时文档只会增长很少,这有望意味着磁盘不断移动的可能性很小,不仅如此,而是一个较小的工作集,从而创建一个更高性能的整体操作。不仅如此,当然所有者的_id
很少会发生变化,因此您最需要投入此数据子集的唯一操作是创建和删除。
回到复杂的排序和分页。有了这些数据,您当然可以通过一次往返获得所有owner
ID,然后在另一次往返中,您可以使用{{1}查询users
表中的所有所有者行以进行常规查询允许你需要的复杂显示。
总而言之,我发现这种结构非常有效。
当然这个结构取决于你的查询,最好把字符串id放在用户身上,但在这种情况下它不会,因为用户可能会拥有许多字符串,因为我会说这是很多 - >字符串端嵌入了很多关系。
希望这会有所帮助,而且我没有绕圈子,
答案 1 :(得分:5)
补充dbaseman的答案:
是的,你的方法似乎没问题。您可以轻松搜索" owner1"所拥有的所有字符串;
db.collection.find({owners: 'author1'})
这是可能的,因为mongodb以特殊方式处理数组。
答案 2 :(得分:3)
在处理嵌入数据时,我建议您熟悉mongo中的Atomicity行为。 一个很好的起点将在这里: http://docs.mongodb.org/manual/core/data-modeling/#atomicity
在您的特定情况下,将用户ObjectId(由Sammaye推荐)添加/删除到“所有者”数组时,您将需要对字符串doc使用a findAndModify()操作以确保写入该文档时,仍然保持数据完整性。
在此操作中,我建议使用以下运算符:
这两个都记录在这里: http://docs.mongodb.org/manual/reference/operators/#update-operators-array
答案 3 :(得分:2)
这看起来像是正确的方法;但请记住,它总是取决于项目的总体情况,目标是什么(性能,灵活性),您打算运行最多的查询,是否需要运行即席查询以及其他因素。通常,使用嵌套文档,如您所写,是使用连接和外键的正确替代方法。
还要记住maximum document size(目前是16MB),如果有很多(如数十万)给定字符串的所有者,这将是一个问题。