免责声明:通过参考数据,我不是指参照完整性
我正在学习nosql,并想了解数据应该如何建模。例如,在CMS应用程序的典型关系数据库中,您可能有两个表:article和author,其中article引用了作者。
在nosql系统中,您可以通过这种方式创建文章文档,因为它们只是disguised object graph
{
title: "Learn nosql in 5 minutes",
slug: "nosql_is_easy",
author: {firstName: "Smarty"
lastName: "Pants"
}
{
title: "Death to RDBMS",
slug: "rdbms_sucks",
author: {firstName: "Smarty"
lastName: "Pants"
}
依旧......
有一天,Smarty Pants先生决定将他的名字改为Regular Joe,因为nosql已经无处不在。在这种用例中,需要扫描每篇文章并更新作者姓名。
所以我的问题是,如何在nosql中建模数据以适应CMS的基本用例,以便性能与RDBMS相比还是更快?例如,mongodb声称CMS是一个用例......
修改:
很少有人建议将数据标准化,如:
article
{
title: "Death to RDBMS",
slug: "rdbms_sucks",
author: {id: "10000001"}
}
author
{
name: "Big Brother",
id: "10000001"
}
但是,由于nosql在设计上缺少连接,因此您必须使用类似mapreduce的函数将数据组合在一起。如果这是您的建议,请评论此类操作的执行情况。
编辑2:
如果您认为nosql不适合需要参考数据的任何类型的数据,请解释原因。这似乎使得nosql的用例相当有限,因为任何合理的应用程序都会包含关系数据。
编辑3:
答案 0 :(得分:4)
如果你这么说,我认为CouchDB是一个NoSQL数据库。
但实际上,我们有通用编程语言和特定于域的语言。同样,CouchDB是特定于域的数据库。
我经常使用CouchDB,但我真的不在乎它是使用SQL还是NoSQL。 CouchDB对我来说很有价值,因为API是100%HTTP,JSON和Javascript。您可以使用浏览器从CouchDB获取HTML,然后通过AJAX查询数据来构建Web应用程序。说这是“不是SQL”是轻描淡写!
无论如何,回到Smarty Pants和Regular Joe。也许他有10万份文件。如果我们刚刚更新了所有内容,那会怎么样?嗯,这是一个相当少量的Javascript。
$.getJSON('/db/_design/cms/_view/by_user?key=Smarty+Pants', {
success: function(result) {
// Change the name right here, in the result objects.
var docs = result.rows.map(function(row) {
row.value.firstName = "Regular";
row.value.lastName = "Joe";
return row.value;
})
// Store it!
$.post('/db/_bulk_docs', {"docs":docs}, function() {
console.log("Done! Renamed Smarty Pants in " + docs.length + " documents!");
})
}
})
是的,这种技术可以让你获得计算机科学课程。但是,我喜欢它。我会在Firebug中编写这段代码。在我的浏览器中。重命名不是原子的,它没有参照完整性。另一方面,它可能会在几秒钟内完成,没人会关心。
你可能会说CouchDB在流行语和基准测试中失败,但却让学校陷入困境。
P.S。 by_user
视图是根据map-reduce构建的。在CouchDB中,map-reduce是 incremental ,这意味着它的执行方式与大多数SQL索引一样。所有查询都以短暂的,可预测的(对数)时间结束。
答案 1 :(得分:4)
您的数据显然是关系型的:文章有作者。您可以像在MongoDB中那样在NOSQL存储中建模数据,就像在关系存储中一样,因为数据库中没有连接,您必须对数据库进行两次调用,这样您才能获得任何东西。 / p>
但是......你可以用NOSQL商店做些什么来对数据进行非规范化以获得更好的性能(单次往返以获得显示文章所需的一切)但是以牺牲即时一致性为代价:折衷始终准确的作者姓名,以获得最终准确的作者姓名。
例如,您可以在文章中使用它:
author: {firstName: "Smarty", lastName: "Pants", _id:DE342624EF }
现在您可以非常快速地显示文章,当有人更改其名称时,您可以启动后台任务以更新所有现有文章,也可以等待定期一致性扫描来修复它。
许多主要网站不再为您提供即时一致性。您所做的更改最终只会被网站上的其他用户看到。
答案 2 :(得分:1)
对于您的具体情况,请使用Flyweight模式,存储对象ID而不是对象实体。
article
{
title: "Death to RDBMS",
slug: "rdbms_sucks",
author: {id: "10000001"}
}
author
{
name: "Big Brother",
id: "10000001"
}
对于一般的mongodb架构设计建议,请阅读the offical documents
答案 3 :(得分:0)
请允许我声明我不是NoSQL的专家。相反,我对它的了解主要是理论上的。
那就是说,我坚信在NoSQL中实现这样的CMS类型系统可能不是最好的方法,因为数据主要是关系型的。
我对此问题的看法是基于您使用的NoSQL系统允许通过“主键”类型结构加载记录的假设。我认为大多数人都这样做,但我确信有一些不这样做。
那就是说,我建议以下列方式存储数据。
对于作者:
{
_KEY: $AUTHOR_GUID,
firstName: "Smarty",
lastName: "Pants",
}
对于帖子本身:
{
title: "Learn nosql in 5 minutes",
slug: "nosql_is_easy",
author: $AUTHOR_GUID,
}
请注意,在上面,我使用_KEY来表示这是“主键”类型的值。
加载帖子后,您可以按照GUID加载作者。
答案 4 :(得分:0)
这篇文章已经存在了一段时间,但我想我会指出另一种方法来处理“连接”和跨文档引用与CouchDB。这是我在CMS中使用的一种方法,我正在(重新)编写使用CouchDB(以前它是为MySQL编写的)。
CMS命名为BlueInk,可以在http://github.com/BigBlueHat/BlueInk的Github上找到。目前重写的重点是文档设计和“渲染引擎”部分,所以没有UI可以说 - 你必须要工艺所有的JSON都是手工制作的。这是我希望尽快解决的问题,但已经足够的回购(一旦安装到CouchDB中),让你知道如何“加入”。
在BlueInk中,页面引用的内容项本身可以包含在一个或多个页面中(或多次包含在同一页面中)。该页面通过其ID引用页面项(如第二个JSON示例中所示)。当通过"page_and_items" view运行时,它将生成可与CouchDB的?include_docs=true
查询参数一起使用的输出,以提取页面文档中内容项引用的全部内容。
视图输出然后通过_list
函数传递,并通过Mustache模板格式化并输出为HTML页面 - 所有这些都在一个GET请求中。
在上面的用例中可以使用与?include_docs=true
一起使用引用ID的相同模式。使用_list
函数完全是“装饰性的”,但它可以帮助重构输出视图JSON或模板化它并输出HTML,CSV,XML等。
答案 5 :(得分:0)
您可以使用playOrm对数据进行建模,并在noSQL存储中进行连接。 playOrm有S-SQL(可伸缩SQL),它是SQL的一个转折点,您可以指定要查询的分区。通过这种方式,您可以从DBMS迁移到noSQL,并且仍然使用您熟悉的工具。