我一直在使用MongoDB数据库层开展Web项目。我有一个特定的实体,我无法正确地映射到文档数据库,认为最好得到一些反馈。
说,我有User和Item集合。用户可以喜欢或不喜欢的项目。项目中也有标签,用户也可以喜欢或不喜欢标签。我需要能够足够快地查找喜欢/不喜欢的计数。
我想出的是这样的(对于项目):
{
name: "Item Name",
statistics : {
likes: 5,
dislikes: 6
},
tags: [
{ name: "Foo", likes: 10, dislikes: 20 },
{ name: "Bar", likes: 5, dislikes: 1 }
]
}
这很不错。但问题是,我需要知道用户是否喜欢/不喜欢标签或项目。现在,我提出的是这样的事情:
{
name: "Item Name",
statistics : {
likes: 5,
dislikes: 6
},
tags: [
{
name: "Foo",
likes: 2,
dislikes: 1,
votes: [
{ user: "user1_id", vote: 1 }, //like
{ user: "user2_id", vote: 1 }, //like
{ user: "user3_id", vote: -1 }, //dislike
]
},
{
name: "Bar",
likes: 0,
dislikes: 0,
votes: []
}
]
}
这看起来很有希望,我在这里看到的最大好处是,如果有人改变主意并且不喜欢以前喜欢的东西,我可以做原子更新。
但是,我希望每个项目大约有10个标签,每个可能有100个选票。然后我为每个项目拥有大约1000个嵌套投票对象。我知道mongodb可以处理16mb文件,但是,将这么多数据存储在一个文档中是否可以?
我应该选择标准化模型吗?也许有“tagvotes”系列和itemvotes系列?实际上对我来说感觉更自然。
如果我在思考关系或理性,那就徘徊吧?
感谢。
答案 0 :(得分:5)
在某些时候,在M和N增长的任何M x N类型的情况下,试图嵌入一切都变得不可能。在你达到这一点之前,你需要创建一个单独的集合并进行客户端连接;但这并不意味着你必须完全正常化。
在这种情况下,请考虑您希望向用户显示哪些视图:显然,您需要显示该项目,它有多少喜欢和不喜欢的内容以及已应用于它的标记集以及每个那些标签是。但是喜欢/不喜欢该对象并喜欢/不喜欢每个标签的实际用户列表可以进入单独的文档(在单独的集合中)。
使用类似这样的模式,您可以执行一个查询以获取项目以及需要与该项目一起显示的所有内容。然后,如果您需要它,只需再查询一次,即可获得当前用户对该项目的意见以及他们投票的所有与该项目相关的标记。
答案 1 :(得分:1)
将这么多数据存储在一个文档中是否可以?
我没有看到每个对象存储的数据的金额存在问题,但是您的读取/更新模式令人担忧:每次获取该项目时,您还将获取所有投票,每个用户的ID等。此外,在添加投票时,您将增长该对象。有时,MongoDB将不得不重新分配您的对象,这需要一些时间。随着时间的推移,它将了解到您经常在增长对象,并且填充因子会增加,但经常增长的对象并不是最好的主意。
如果有人改变主意并不喜欢以前喜欢的东西,我可以做原子更新。
这有点棘手。您可以使用$pull
和$push
,但我不知道如何保持likes
和dislikes
计数同步。而且,如果用户真的改变了主意,会发生什么?您必须同时执行$push
和$pull
,如果我没记错的话,这是不可能的。
只是想知道我是在考虑关系还是理性?
两者。这是一个关系问题: - )
现在我想得出结论,你应该对计数进行非规范化并将关系存储在不同的集合中,但Hightechrider已经写过了。太慢了。 ;-)