【问题标题】:PouchDB delete document upon successful replication to CouchDB成功复制到 CouchDB 后 PouchDB 删除文档
【发布时间】:2019-07-10 06:51:10
【问题描述】:

我正在尝试实施如下所述的流程:

  1. 在设备中创建sale_transaction 文档。
  2. sale_transaction文件放入Pouch。
  3. 由于 Pouch 和 Couch 之间存在实时复制,因此让 sale_transaction 文档流向 Couch。
  4. sale_transaction 文档成功复制到 Couch 后,删除 Pouch 中的文档。
  5. 不要让 Pouch 中的 deleted sale_transaction 文档流过 Couch。

目前,我已经实现了两个数据库的双向同步,我正在过滤从 Couch 到 Pouch 的每个文档,反之亦然。

对于从 Couch 到 Pouch 的复制,我不想让 sale_transaction 文档通过,因为我只能从 Couch 获取这些文档。

PouchDb.replicate(remoteDb, localDb, {
   // Replicate from Couch to Pouch
   live: true,
   retry: true,
   filter: (doc) => {
      return doc.doc_type!=="sale_transaction";
   }
})

对于从 Pouch 到 Couch 的复制,我设置了一个过滤器,不让 deleted sale_transaction 文档通过。

PouchDb.replicate(localDb, remoteDb, {
   // Replicate from Pouch to Couch
   live: true,
   retry: true,
   filter: (doc) => {
      if(doc.doc_type==="sale_transaction" && doc._deleted) {
         // These are deleted transactions which I dont want to replicate to Couch
         return false;
      }
      return true;
    }
}).on("change", (change) => {
   // Handle change
   replicateOutChangeHandler(change)
});

我还实现了一个更改处理程序来删除 Pouch 中的 sale_transaction 文档,在写入 Couch 之后。

function replicateOutChangeHandler(change) {
   for(let doc of change.docs) {
      if(doc.doc_type==="sale_transaction" && !doc._deleted) {
         localDb.upsert(doc._id, function(prevDoc) {
            if(!prevDoc._deleted) {
               prevDoc._deleted = true;
            }
            return prevDoc;
         }).then((res)=>{
            console.log("Deleted Document After Replication",res);
         }).catch((err)=>{
            console.error("Deleted Document After Replication (ERROR): ",err);
         })
      }
   }
}

一开始似乎数据流是正常的,但是当我从 Couch 获取sale_transaction 文档,然后进行一些编辑时,我不得不重复在 Pouch 中编写文档的过程,然后让它流到 Couch,然后在 Pouch 中将其删除。但是,在对同一文档进行一些编辑后,Couch 中的文档也已被删除。

我是 Pouch & Couch 的新手,特别是 NoSQL,我想知道我在这个过程中是否做错了什么。

【问题讨论】:

  • 您为什么不简单地在内存中编辑/创建文档,然后他们将它们直接推送到 CouchDB?
  • @AlexisCôté 我在考虑设备无法访问互联网的情况。因此,如果我将文档推送到 Pouch,并且没有互联网连接,我将依靠 Pouch 的本机复制将文档同步到 Couch。

标签: javascript couchdb pouchdb nosql


【解决方案1】:

对于您上面描述的这种情况,我建议您按如下方式调整您的方法:

从 CouchDB 创建一个 PouchDB 数据库作为复制目标,但将此数据库视为 CouchDB 数据库的只读镜像,应用您需要的任何转换以从本地存储中删除某些文档类型。为了这个例子,我们称这个数据库为mirrormirror 数据库只能通过转换复制从规范的 CouchDB 数据库进行单向更新。

创建一个独立 PouchDB 数据库来存储您的所有销售交易。为了我们这个例子,我们称这个数据库为user-data

当用户创建新的销售交易时,此文档将写入user-data。监听user-data上的变化,当一个文档被创建时,使用变化处理器来创建文档并将其直接写入CouchDB。

此时,CouchDB 正在从user-data 接收销售交易,但您的转换复制正在防止它们污染mirror。您可以保留它,在这种情况下,user-data 将拥有所有销售交易的本地副本。注销时,您可以删除 user-data 数据库。或者,您可以在更改处理程序中添加一些更复杂的逻辑,以便在 CouchDB 收到文档后将其删除。

如果你真的想变得花哨,你可以做一些更精致的事情。将销售事务写入 CouchDB 后将其保留在 user-data 中,并在从 CouchDB 到 mirror 的转换复制中查找这些新创建的销售事务文档。与其删除它们,不如去掉它们的 _id_rev 字段以外的任何内容,并将它们用作“收据”。当其中一个 ID 与 user-data 中的 ID 匹配时,可以安全地删除该文档。

无论您选择哪种方法,我建议您将本地 PouchDB 的 _changes 提要视为工作队列,而不是将所有这些复杂的逻辑放在复制过滤器中。上述方法都应该能够在离线情况下存活而不会引入冲突,并且在连接恢复时可以很好地恢复。我推荐最后一个解决方案,尽管它可能比其他解决方案多一点工作。希望这会有所帮助。

【讨论】:

    【解决方案2】:

    可能是删除的附加字段 - 从而将记录标记为删除。 然后在 Pouch 和 Couch 上运行定期例程,扫描标记删除记录并删除它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多