CouchDB中1:1关系的划分

CouchDB中1:1关系的划分,couchdb,Couchdb,我目前正在设计一个数据库结构(这里避免使用术语scheme很奇怪),并遇到了一些问题。我将用一个类似的例子来激发我的问题 设想一个博客条目数据库。每个博客条目都有0..n条评论、0..m个标记和0..r条目的用户投票(向上/向下) 当然,我可以将所有内容放在一个大的JSON对象中,每个条目都有一个公共对象,包括注释、标记和投票作为字段 但是,当有许多并发更改时(至少在我的实际应用程序中有),这很容易发生冲突。所以我想把我的结构分成几个文档。每个条目一份,每个条目一份(收集)文档用于评论,一份用于

我目前正在设计一个数据库结构(这里避免使用术语scheme很奇怪),并遇到了一些问题。我将用一个类似的例子来激发我的问题

设想一个博客条目数据库。每个博客条目都有0..n条评论、0..m个标记和0..r条目的用户投票(向上/向下)

当然,我可以将所有内容放在一个大的JSON对象中,每个条目都有一个公共对象,包括注释、标记和投票作为字段

但是,当有许多并发更改时(至少在我的实际应用程序中有),这很容易发生冲突。所以我想把我的结构分成几个文档。每个条目一份,每个条目一份(收集)文档用于评论,一份用于标记,一份用于投票

我还设置了一个固定名称模式。博客条目具有UUID创建时,评论、标签和投票的文档命名为
:(标签|投票|评论)
。 因此,只要知道博客文章的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中处理关系的强大工具。