我正在阅读MongoDB,但仍然无法理解在哪些情况下我更喜欢面向文档的数据库而不是像Postgres这样的传统数据库。
请考虑以下内容:我有一个博客,其中包含帖子,用户可以在帖子上撰写评论。所以我创建了两个集合:users
和posts
。每个post
都包含一系列嵌入式文档 - comments
,因此每次从数据库加载post
时,我都会自动获取所有comments
。这很好,事实上Mongo似乎是一个更好的选择,如果我知道肯定关系不会改变。但一切都确实如此。
假设我决定在他/她的个人资料页面上显示用户的评论。我必须在posts.comments.user_id
上创建索引,然后从posts
选择user._id
。所以这与我在RDBMS中做的基本相同。或者我必须将所有comments
从posts
复制到users
并且手动确保这两个集合在未来保持同步(无触发器和放大器) ; Mongo没有交易。)
现在我为帖子添加了一个新字段,例如rating
,对于那些已经存在的记录,我想设置rating = number of comments
。但我不能做这种大规模更新。要么为所有更新的文档设置相同的值({ $set: {rating: 1} }
),要么我必须逐个手动循环。
如何找到最活跃的用户?因为没有joins
- 首先,我必须提取顶部posts.comments.user_id
并将其保留在某处。然后一次_id
,然后选择user.name
。这可以通过将user.name
保留在comment
中来解决。但是如果以后我需要更多的字段呢?
我有什么不对吗?这三种情况似乎是博客应用程序的简单扩展。如果我从一开始就不是100%肯定关系和统计的结构,并且......(在99%的实际案例中)我不应该使用Mongo吗?
答案 0 :(得分:2)
非常有趣和有启发性的问题。
需求的变化意味着软件的变化。将评论从帖子转移到用户肯定会是一个非常大的变化,但我仍然认为使用MongoDB这样的改变可能比使用RDBMS更少痛苦。例如,可以修改应用程序,以便它可以同时处理两个变体:用户的帖子和评论中的评论。这样,数据可以随时间迁移到新结构而不是一次全部迁移到新结构。 - 在用户和帖子中保留评论两个对我来说似乎是一个相当糟糕的决定。如果数据经常变化,那么不就会使其非常规化。
您描述的更新在任何编程语言或MongoDB的本机javascript shell中实现都是微不足道的。查询语言本身不允许这种复杂更新这一事实并不意味着使用MongoDB无法轻松完成。我认为查询语言比完整的SQL更流线型实际上是一件好事。
仔细的非规范化(通过将user.name放入注释本身)确实可以在这里提供帮助。由于user.name很少会更改,因此对于这种非规范化而言,这比将注释放入用户和帖子更好。再一次,如果你有选择地动态地执行这个操作,MongoDB的灵活性就会开始大放异彩 - 当你到达时,可以将user.name放入注释中,但可以编写应用程序以便它可以处理这两种情况:如果用户.name不在它被查找的注释中(然后可能写入注释以保存将来的查找)。您可以在评论中“缓存”更多属性。
通常,MongoDB可以更灵活,更灵活地思考数据结构并在数据库中实现它们。许多程序员发现比SQL的刚性更直观,更易于使用。但是没有技术只有优势,而且你总能找到问题,其中一种方法可以带来比另一种方法更好,更优雅的解决方案。
答案 1 :(得分:0)
您只需通过编程语言解决问题。修改SQL查询以改变结果是本能的,但您只需使用javascript来提取新的数据。