如何有效地将 CouchDB 与规范化数据一起使用?

Posted

技术标签:

【中文标题】如何有效地将 CouchDB 与规范化数据一起使用?【英文标题】:How do I effectively use CouchDB with normalized data? 【发布时间】:2014-08-19 20:31:43 【问题描述】:

我花了很长时间(日历)来了解 CouchDB 和 map/reduce 以及如何将它用于各种用例。我让自己理解的一个挑战是如何有效地将它用于标准化数据。互联网上的来源只是以“不要将其用于标准化数据”而停止。我不喜欢缺乏对如何有效使用标准化数据的分析!

我发现的一些更好的资源如下:

CouchDB: Single document vs "joining" documents together http://www.cmlenz.net/archives/2007/10/couchdb-joins

在这两种情况下,作者都很好地解释了当文档之间存在非规范化的共性时,当需要加入文档时如何进行“加入”。但是,如果我需要加入两个以上的规范化“表”,则用于查询一行数据的视图排序技巧不起作用。也就是说,您似乎需要某种关于连接中所有元素的数据才能存在于将参与连接的所有文档中,因此,您的数据没有被规范化!

考虑以下简单的问答示例(问题/答案/答案评论):

 id: "Q1", type: "question", question: "How do I...?" 
 id: "A1", type: "answer", answer: "Simple... You just..." 
 id: "C1", type: "answer-comment", comment: "Great... But what about...?" 
 id: "C2", type: "answer-comment", comment: "Great... But what about...?" 
 id: "QA1", type: "question-answer-relationship", q_id:"Q1", a_id:"A1" 
 id: "AC1", type: "answer-comment-relationship", a_id:"A1", c_id:"C1" 
 id: "AC2", type: "answer-comment-relationship", a_id:"A1", c_id:"C2" 
 id: "Q2", type: "question", question: "What is the fastest...?" 
 id: "A2", type: "answer", answer: "Do it this way..." 
 id: "C3", type: "answer-comment", comment: "Works great! Thanks!" 
 id: "QA2", type: "question-answer-relationship", q_id:"Q2", a_id:"A2" 
 id: "AC3", type: "answer-comment-relationship", a_id:"A2", c_id:"C3" 

我想得到一个问题,它的答案,以及它的所有答案的 cmets,并且只有一个查询从数据库中没有其他记录。

使用上面的数据集,在较高级别上,您需要为每种记录类型提供视图,请求特定的 question 并记住 id,然后在另一个视图中使用 @987654326 @id查找question-answer-relationshiptype指定的关系,然后在另一个视图中查找id得到的answerquestion-answer-relationshiptype,以此类推,在一系列请求中聚合“行”。

另一种选择可能是创建某种应用程序,该应用程序执行上述处理,以所需格式缓存非规范化文档,自动对正在更新的规范化数据做出反应。这感觉很尴尬,就像重新实现已经存在/应该存在的东西。

在了解了所有这些背景之后,最终的问题是:有没有更好的方法来做到这一点,让数据库而不是应用程序来工作?

提前感谢任何人分享他们的经验!

【问题讨论】:

【参考方案1】:

如果我使用传统的关系数据库,您拥有的文档模型就是我会做的,因为您可以使用这些 id 更自然地执行连接。

然而,对于文档数据库,这会带来复杂性,因为使用 MapReduce '加入'文档并不是一回事。

在您提出的问答场景中,我将其建模如下:


    id: "Q1",
    type: "question",
    question: "How do I...?"
    answers: [
        
            answer: "Simple... You just...",
            comments: [
                 comment: "Great... But what about...?" ,
                 comment: "Great... But what about...?" 
            ]
        ,
        
            answer: "Do it this way...",
            comments: [
                 comment "Works great! Thanks!" ,
                 comment "Nope, it doen't work" 
            ]
        
    ]

这可以解决来自数据库的read 的很多问题,但它确实使您的write 更加复杂,例如,在为答案添加新评论时,您需要

    从 CouchDB 中取出文档。 遍历答案并找到正确的位置,并将评论推送到数组中。 将文档保存回 CouchDB。

如果answer 有很多(例如 1 个问题产生 1000 个答案),我只会考虑将它们作为单独的文档吐出,否则将它们打包在一个文档中会更容易。但即使在这种情况下,请尝试将关系信息放入文档中,例如


    id: "Q1",
    type: "question",
    question: "How do I...?"


    id: "A1",
    type: "answer",
    answer: "Simple... You just..."
    question_id: "Q1"


    id: "C1",
    type: "comment",
    comment: "Works great! Thanks!"
    answer_id: "A1"

这可以使您的write 操作更轻松,但您需要创建viewjoin 的文档,以便它通过一个请求返回所有文档。

请始终牢记,view 的返回结果不一定是像 sql 查询中的行那样的扁平结构。

【讨论】:

感谢您抽出宝贵的时间来创建如此深思熟虑的回复!但是,您的建议完全违背了我希望保持数据标准化的约束! 在这种情况下,您应该选择为规范化数据制作的 RDBMS 数据库。 我认为我正在意识到(我已经在各处阅读过)是,像 Couch 这样的数据库的分布式特性需要对数据进行非规范化,因为您确实可以获得当每个节点都拥有完成其工作所需的一切时,它是分布式的。我遇到的麻烦是管理变得非规范化的东西只是感觉......混乱。当然,对那些假定最终会导致 bot 相同的事物保持适当的标签并不是小菜一碟。 @Buddy,请注意 CouchDB 不会跨节点分发 Views,只有它的数据是(通过数据复制)。而且 CouchDB 不会将计算分派给节点,每个节点/服务器都是独立工作的。

以上是关于如何有效地将 CouchDB 与规范化数据一起使用?的主要内容,如果未能解决你的问题,请参考以下文章

何时使用 CouchDB 与 RDBMS [关闭]

我可以使用 CouchDB mobile 代替 localStorage 吗?

Node.js 与 CouchDB 和 Backbone.js 一起使用,如何提供 json?

将 couchdb 与 Android 应用程序捆绑在一起

有效地将给定令牌与数据库中的散列,盐渍令牌进行比较

将 CouchDB 与 Node.js 库一起使用