CouchDB中1:1关系的划分
我目前正在设计一个数据库结构(这里避免使用术语scheme很奇怪),并遇到了一些问题。我将用一个类似的例子来激发我的问题 设想一个博客条目数据库。每个博客条目都有0..n条评论、0..m个标记和0..r条目的用户投票(向上/向下) 当然,我可以将所有内容放在一个大的JSON对象中,每个条目都有一个公共对象,包括注释、标记和投票作为字段 但是,当有许多并发更改时(至少在我的实际应用程序中有),这很容易发生冲突。所以我想把我的结构分成几个文档。每个条目一份,每个条目一份(收集)文档用于评论,一份用于标记,一份用于投票 我还设置了一个固定名称模式。博客条目具有UUID创建时,评论、标签和投票的文档命名为CouchDB中1:1关系的划分,couchdb,Couchdb,我目前正在设计一个数据库结构(这里避免使用术语scheme很奇怪),并遇到了一些问题。我将用一个类似的例子来激发我的问题 设想一个博客条目数据库。每个博客条目都有0..n条评论、0..m个标记和0..r条目的用户投票(向上/向下) 当然,我可以将所有内容放在一个大的JSON对象中,每个条目都有一个公共对象,包括注释、标记和投票作为字段 但是,当有许多并发更改时(至少在我的实际应用程序中有),这很容易发生冲突。所以我想把我的结构分成几个文档。每个条目一份,每个条目一份(收集)文档用于评论,一份用于
:(标签|投票|评论)
。
因此,只要知道博客文章的ID,我就可以构建引用文档的ID。使用视图时,我可以使用视图排序功能“加入”或利用include\u docs=true
通过使用更新处理程序,我可以进一步减少添加注释等冲突的更改。处理程序只需获取新注释,并将其放入:comments
文档中
这是一种可行的方法还是有更好的连接方法?这样构建ID是一种不好的做法吗
提前感谢据我所知,coach并不打算处理文档之间的1:1关系,因为单个“事物”的不同方面包含在不同的文档中。您可以处理所有这些,而无需特定的收集文档 每个注释可能都有自己的文档。Christopher Lenz描述了如何在这种情况下创建类似联接的视图
另一方面,标签和向上/向下的投票应该在其所有者内部保持内联。是的,您仍然存在编辑冲突问题,但这些冲突在任何情况下都可能很容易解决。我认为把数据库结构复杂化到那种程度是不值得的。(尽管如果审核上/下投票很重要,您可以为每次投票使用一个单独的文档,并使用reduce查询来查找文档的最终分数。)Leadstorm提出了一个很好的观点。我不会说CouchDB绝对不支持1:1;你只需要理解其中的含义。基本上,您不能同时以原子方式更新这两个文档。坦率地说,对于许多类型的应用程序来说,这一特性被夸大了 视图排序是将相关文档“连接”在一起的一种很好的方法。它非常强大
另一个需要考虑的是CouCHDB 0.11和稍后的特性,以便在视图中用ID引用相关文档。在简的博客文章中读到这一点。基本上,当您发出一个键/值时,您可以“欺骗”include_docs=true功能以返回任何文档,而不仅仅是调用
emit()
时正在处理的文档。比较:
function(doc) {
// The old way. include_docs would include this document (doc).
emit(some_key, some_value);
// The new way. include_docs will fetch some_other_doc_id and return that.
emit(some_other_key, {"_id": some_other_doc_id});
}
我所见过的处理文档关系的最常见方法,更重要的是,当多个用户可以同时写入这些文档时,更新这些文档,就是将文档与操作链接起来。例如,不要将博客文章的评级视为一个组成部分,而是将每个评级视为一个不同的操作,并为其创建一个文档。然后使用Map/Reduce的强大功能来聚合所有这些操作 评级行动文件:
{
"docType": "rating",
"of": {
"id": "ID of the blog/video/comment document",
"type": "blog/video/comment"
},
"by": "the user's document ID",
"rating": 3
}
地图功能:
function(doc)
{
if(doc.docType == "rating")
emit([doc.of.id, doc.of.type], doc.rating);
}
function(keys, values, rereduce)
{
return sum(values);
}
减少功能:
function(doc)
{
if(doc.docType == "rating")
emit([doc.of.id, doc.of.type], doc.rating);
}
function(keys, values, rereduce)
{
return sum(values);
}
现在,您可以轻松获得应用程序中特定项目、项目类型(例如,排名前10位的评论)或每种媒体类型的评级。这没有CouchDB 0.11.x和即将推出的1.0中一些更酷的特性
当然,你可能在寻找一个不同的答案——如果是这样的话,请告诉我
最后,我认为CouchDB可以很好地处理1:1关系(至少根据我的定义):没有什么可以阻止您在文档B中包含文档A的id。正如我在问题中所述,自动包含引用id和视图排序规则是CouchDB中处理关系的强大工具。