我们有两种文档“类型”:Post
和 User
:
典型帖子:
{
"_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", ... ]
}
在显示帖子
的网页上,该帖子的用户名
(以及有关该用户的任何其他可更改信息)会显示在帖子旁边。类似于SO:
这是 SQL JOIN 完美的情况的典型示例,但当然 CouchDB 不支持类似的东西。相反,我们可以创建一个 View ,在 Post
的 _id
上对 User
文档和 Post
文档进行索引。像这样:
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
的 _id
高效地检索所需的所有信息。
但是,如果我想创建一个列出所有 IsFeatured == true
的帖子以及所有用户数据的 View ,我就会陷入困境!
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 中可能吗?
最佳答案
由于这是一种不同的技术,因此需要权衡。有时,尽管事情看起来在短期内会占用更多资源(额外的请求),但它可能无关紧要,并且从长远来看,如果您需要此类事情,可能会提供显着的可扩展性。
CouchDB 可以同时处理许多不同的“数据库”,您可以将其视为不同的模型空间。因此,使用相同的 CouchDB 运行实例,您可以拥有 /users
和 /posts
。这绝对不需要在 CouchDB 的配置或性能方面进行额外的工作。
这可以使您的 map 代码更加直接,因为您不需要拥有“架构”字段并将其合并到每个 map 函数中。
此外,您可以(并且应该)在给定的设计 View 中拥有多个不同的映射/归约对。这很重要,因为如果您有两个不同的文档“Schema”emit(doc.id, doc.val)
,您如何区分哪个是用于减少目的的。
查看数据的更惯用的 CouchDB 方法是不保存用户的 post_ids。只需帖子上的用户 ID,然后就有一个类似于以下帖子的 map :
(doc) ->
emit([doc.user_id, doc.isFeatured], null);
emit([doc.isFeatured, doc.createdAt], doc.user_id);
然后,使用 ?start_key=['12345345345234234']&end_key=['12345345345234234',{}]
等参数向 View API 发出请求将获取他们的所有帖子。
只要使用 ?key=['12345345345234234', 1]
就能获得他们的精选帖子。
第二次发送还使您能够快速获取整个系统中按日期排序的所有帖子 - 如果您需要这些数据,则可以查看谁发布的帖子,而无需将整个帖子发送到管道中.
关于nosql - 如何最好地解决 CouchDB 的非 RDBMS 限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15440332/