2

我们有两种文档“类型”:PostUser

典型帖子:

{
   "_id": "3847345345",
   "Schema": "Post",
   "Text": "Hello World! This is a post!",
   "IsFeatured": true,
   "UserID": "12345345345234234"
}

典型用户:

{
   "_id": "12345345345234234",
   "Schema": "User",
   "Username": "georgepowell"
   "PostIds": ["3847345345","5135345345","9987453236", ... ]
}

在显示 的网页上,PostUsername帖子的 (以及有关该用户的任何其他可变信息)显示在帖子旁边。类似于 SO: 用户信息

这是一个典型的例子,说明 SQL JOIN 是完美的,但当然 CouchDB 不支持这样的事情。相反,我们可以创建一个视图来索引User文档和'sPost上的文档。像这样:Post_id

function(doc) {
    if (doc.Schema = 'Post') {
        emit([doc._id, 0], null);
    } else if (doc.Schema = 'User') {
        foreach (string id in doc.PostIds) // not javascript I know. shhh
            emit([id, 1], null);
    }
}

效果很好,因为我们可以有效地检索给定单个Post's所需的所有信息_id

但是,如果我想创建一个列出所有帖子IsFeatured == true以及所有用户数据的视图,我会卡住!

function(doc) {
    if (doc.Schema = 'Post' && doc.IsFeatured) {
        emit([doc._id, 0], null);
    } else if (doc.Schema = 'User') {
        foreach (string id in doc.PostIds)
            emit([id, 1], null); // I can't check if the post is featured!
    }
}

我是否达到了 CouchDB 对关系数据的限制?或者这种索引在 CouchDB 中是否可行?

4

1 回答 1

2

由于它是一种不同的技术,因此需要权衡取舍。有时虽然事情看起来在短期内会占用更多资源(额外的请求),但它可能是无关紧要的,从长远来看,如果你需要这种东西,可能会提供显着的可扩展性。

CouchDB 可以同时处理许多不同的“数据库”,您可以将它们视为不同的模型空间。因此,使用相同的 CouchDB 运行实例,您可以拥有/users/posts. 这绝对不需要 CouchDB 的配置或性能方面的额外工作。

这可以使您的地图代码更直接,因为您不需要拥有“架构”字段并将其合并到每个地图功能中。

此外,您可以(并且应该)在给定的设计视图中拥有多个不同的 map/reduce 对。这很重要,因为如果您有两个不同的文档“架构” emit(doc.id, doc.val) ,您如何分辨哪个用于减少目的。

查看数据的更 CouchDB 惯用方式是您不将 post_ids 保存在用户身上。只是 Posts 上的 UserID,然后为 Posts 提供类似以下的地图:

(doc) ->
  emit([doc.user_id, doc.isFeatured], null);
  emit([doc.isFeatured, doc.createdAt], doc.user_id);

然后对视图 API 的请求带有参数 like?start_key=['12345345345234234']&end_key=['12345345345234234',{}]会得到他们所有的帖子。

一个?key=['12345345345234234', 1]人只会得到他们的特色帖子。

第二次发出还使您能够快速获取按日期排序的整个系统中的所有帖子——如果您想要这些数据,请注明是谁制作的,而无需将整个帖子发送到管道中。

于 2013-03-22T21:17:10.467 回答