【问题标题】:Does CouchDB supports referential integrity?CouchDB 是否支持参照完整性?
【发布时间】:2010-12-29 09:24:21
【问题描述】:

我是 CouchDB 的新手,正在学习它。我没有遇到 CouchDB 对引用完整性的支持。 我们可以为 CouchDB 文档中的字段创建外键吗?

例如是否可以确保订单文档中使用的供应商名称在供应商数据库中可用?

CouchDB 是否支持参照完整性? 是否可以将文档中的字段设置为主键?

【问题讨论】:

    标签: couchdb referential-integrity


    【解决方案1】:

    不,CouchDB 本身不做外键,所以你不能让它为你处理系统的引用完整性。您需要在应用程序级别处理供应商检查。

    至于是否可以将字段设置为主键,主键是_id字段,但是可以使用任何有效的json作为db上视图的键。因此,例如,您可以创建以供应商为键的订单视图。

    类似

    function(doc) {
      if (doc.type == 'order')
        emit(doc.vendor,doc);
    }
    

    将抓取数据库中具有类型属性和值顺序的所有文档,并使用它们的供应商作为键将它们添加到视图中。

    Intro to CouchDB views

    【讨论】:

      【解决方案2】:

      这些问题是非常具体的关系数据库。

      在 CouchDB 或任何其他非 RDBMS 中,您不会像在 RDBMS 中那样存储数据,因此以这种方式设计关系可能不是最好的。但是,为了让您了解如何执行此操作,假设您有一份供应商文档和一堆需要“关联”回供应商文档的订单文档。

      没有主键,文档有一个 _id,它是一个 uuid。如果您有供应商的文档,并且要为订单等内容创建新文档,则可以参考供应商文档 _id。

      {"type":"order","vendor-id":"asd7d7f6ds76f7d7s"}
      

      要查找特定供应商的所有订单,您将有一个类似的地图视图:

      function(doc) { if (doc.type == 'order') {emit(doc['vendor-id'], doc)}}
      

      文档 _id 不会更改,因此即使您更改了供应商文档上的其他属性(例如他们的姓名或帐单信息),也不会更改“完整性”。如果您将供应商文档中的供应商名称或其他属性直接粘贴到订单文档中,如果您想批量更改它们,则需要编写一个脚本。

      希望能有所帮助。

      【讨论】:

      • 参照完整性是自己动手做的,换句话说。程序员必须记住首先创建供应商文档,然后编写引用其 _id 的项目,因为 CouchDB 无法为它们强制执行此操作。同样,删除供应商时,程序员必须记住自己首先删除与供应商关联的订单,然后再删除供应商——CouchDB 不会为他们这样做。所以CouchDB会让你不断地步入不一致的状态;不支持保护它。
      • 我不会将没有引用的悬空文档称为“不一致状态”,​​因为在这种情况下,状态是来自将被删除的其他文档的引用。但是您在这里对语义的描述是准确的。引用只是索引,删除文档并不会推断出一些更大的事务会清理反向引用,尽管它会清理前向引用。
      • 更重要的是,couchdb 服务器支持 REST-3(如果需要,您可以使用设计文档构建 REST-4 功能)。应用“参照完整性”这个术语对于文档数据库来说并没有比对于视频游戏更有意义。它不是关系数据库,也不假装是。
      【解决方案3】:

      虽然无法创建 FK 约束,但可以使用 Couch 的 Validate 函数

      function(newDoc, oldDoc, userCtx, secObj) {
          if(newDoc && newDoc.type) switch(newDoc.type){
              case 'fish':
                  var allSpecies = ['trout','goldfish'];
                  if(!allSpecies.contains(newDoc.species)){
                      throw({forbidden : 'fish must be of a know species'});
                  }
                  break;
              case 'mammals':
                  if(!['M','F'].contains(newDoc.sex)){
                      throw({forbidden : 'mammals must have their sex listed'});
                  }
                  break;
          }
      }
      

      现在,如果一个人真的很聪明(我不是),他们可能会调用数据库本身来获取物种列表......这将是一个外键。

      您可能还想阅读以下内容: How do I DRY up my CouchDB views?

      【讨论】:

        猜你喜欢
        • 2013-06-17
        • 1970-01-01
        • 2010-09-26
        • 1970-01-01
        • 2011-09-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多