【问题标题】:Recursive delete in PouchDb/CouchDb?PouchDb/CouchDb 中的递归删除?
【发布时间】:2017-09-04 15:20:15
【问题描述】:

我正在实现一个使用 PouchDB 同步到 Cloudant 上的 CouchDB 的应用程序。我有一个递归的类别层次结构。

服装

  • 上衣

    • 衬衫
      • T 恤
      • 正装衬衫
    • 夹克
      • 轰炸机
      • 摩托车
  • 下装

    • 裤子
    • 短裤

我存储它的方式是使用“类别”类型,每个都有一个“parentId” - 没有父母的那些是根节点。这样一来,我猜父母就像一种外键。

首先,我不知道这是否是存储它的正确方法,但它似乎在我的应用程序中运行良好。问题是当我想删除时我该怎么办? 例如,如果我想删除“Tops” - 我必须递归地遍历树并为每个项目执行删除?这真的是正确的方法吗? 看起来像同步,它会很“健谈” 在上述情况下,我最终将不得不触发 3 次查询和 4 次删除??

请赐教

【问题讨论】:

    标签: javascript couchdb pouchdb cloudant nosql


    【解决方案1】:

    您似乎已经将关系数据模型映射到文档存储中。

    除非有充分的理由不这样做,否则我建议您使用一个“清单”文档,其中存储您正在谈论的所有信息?那么你所说的删除将是这样的:

    db.get('inventory').then(function(doc) {
      delete doc.tops
      return db.put(doc);
    }).then...etc
    

    在 OP 的 cmets 之后更新

    大多数人都这样做,他们以非常理性-DB的心态来处理文档存储。我推荐两种不同的思维方式转变:

    1. 将文档存储想象成更像是获取程序在 RAM 中的对象,然后将它们按原样保存到磁盘中。
    2. 让您的默认成为“我所有数据的一个单一文档”,并且只有在有理由时才制作一个单独的文档。

    创建多个文档可能还有其他原因,但对我而言,两个主要原因是:

    1. 唯一性:文档的_id 是 CouchDB 中唯一可以为您提供系统范围(或实际上是 DB 范围)机制/检查/约束的东西。因此,我将用户等具有唯一用户名的内容放入他们自己的文档中。
    2. 避免冲突:如果您有多个客户端更新相同的数据,例如。客户订单进入您的系统,尤其是多个节点相互复制。将事情分开,这样并发写入就不会发生在同一个文档上,这会让您的生活更轻松。

    除了这些原因,我建议将所有内容都放在一个文档中,然后创建有意义的视图,这样您就可以获得所需的数据。

    所以对于您的具体后续问题:

    您是说有 1 个文档来托管完整的树吗?

    是的,正如我上面所说,我建议使用一个“库存”文档

    这是存储此类数据的常用方法吗?

    我不知道有多常见/多不常见,我知道很多人都会犯您所犯的错误,并以关系的心态来处理文档存储,所以这可能很常见。虽然这不是一个好方法,并且会导致很多麻烦,因为文档存储没有与 RDBMS 相同的功能,例如。缺少多个文档更新的事务。

    这种方法有什么缺点吗?

    除了我上面提到的唯一性和冲突的东西,没有。

    如果我有“衬衫 1”,我希望它属于上衣/衬衫/T 恤,所以需要某种 ID

    想想你将如何在 RAM 中做到这一点。

    例如。而不是你想的结构,你可能有这个文档结构:

    {
      "_id": "inventory",
      "skus": {
        "123456": {
          "sku": "123456",
          "name": "Purple T-Shirt",
          "tags": [ "top", "t-shirt", "shirt", "purple" ]
        },
    
        # ...
    }
    

    然后在视图中您将按标签生成数据查找,例如:

    function(doc) {
      if(doc._id == "inventory") {
        for(var sku in doc.skus) {
          var item = doc.skus[sku]
          item.tags.forEach( function(tag) { emit( tag, sku ) })
        }
      }
    }
    

    然后您可以使用该视图查找您想要的任何 sku,然后您可以使用:doc.items[sku] 来检索它。或者,如果您愿意在索引中包含该数据,则可以将该项目放入您的 emit 输出中。

    【讨论】:

    • 您是说有 1 个文档来托管完整的树吗?我最初想到了这一点,但不知何故似乎“错误”——这是存储此类数据的常用方法吗?这种方法有什么缺点吗?
    • 随后,我需要存储对特定树节点的引用。例如,如果我有“衬衫 1”,我希望它属于上衣/衬衫/T 恤,所以需要某种 ID
    • 感谢您的更新-您说您为不同的用户使用不同的文档-这不是固有的安全问题吗?任何用户都不能只查询“全部”吗?或者您是否正在使用类似代理的中间设置来限制特定用户可以访问的内容?此外,如果您将整个“库存”存储在一个对象中,我想不利的一面可能是数据的大小来回移动 - 每次有任何更新时,您都会更新整个数据存储,对吧?对于移动应用,这可能是个问题,除非它只是偶尔发生的定时同步。
    • 是的,我的数据库和用户之间有一个应用程序/代理。没有用户可以直接查询 CouchDB。重新调整数据的大小,是的,如果我对数据结构的非常特定部分进行了大量更新,那么我会考虑将其拆分为多个文档。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-07
    • 2015-10-28
    相关资源
    最近更新 更多