PouchDB和Couchbase中的多个唯一字段约束和最终冲突解决

时间:2016-03-03 19:27:06

标签: pouchdb

我无法找到适当的解决方案来处理" 最终冲突" (当我有多个唯一字段限制的文档时,请参阅http://pouchdb.com/guides/conflicts.html了解"最终冲突"描述),例如唯一用户名约束和用户注册文档的唯一电子邮件约束或具有唯一名称和标题的文章文档+所有文档都使用 Ionic + PouchDB Couchbase Sync Gateway 在移动设备上进行实时复制。

我们假设Article文档具有唯一name约束和唯一title约束。

1)。我有Article文档,如下所示:

{
  "_id": "article::3808cea0-bb99-11e5-9ba4-315d40280ab9",
  "_rev": "1-8b8076d3fef9994ca65a516532c5f975"
  "type": "Article",
  "name": "name1",
  "title": "title1",
  "owner": "user-id-here"
}

2)。另外,我使用" _id "为每个唯一字段(请参阅Unique constraints in couchdbhttps://kfalck.net/2009/06/29/enforcing-unique-usernames-on-couchdb)创建单独的约束文档。键入格式" {doc type} - constraint-unique - {unique property / field name} :: {sha256中属性的哈希值} "。

所以,对于上面提到的" name1 "和" title1 "我创建了两个" ConstraintUnique " name字段和title字段的文档/占位符。

独特"名称"字段占位符doc:

{
  "_id": "article--constraint-unique--name::e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
  "_rev": "1-de7e0636632764e97880f362d50598b7",
  "type": "ConstraintUnique",
  "docRef": "article::3808cea0-bb99-11e5-9ba4-315d40280ab9",
  "propertyName": "name",
  "propertyValue": "name1"
}

独特"标题"字段占位符doc:

{
  "_id": "article--constraint-unique--title::5018e26faaec56a465e61aaeb752c2984c8a6d6305c8496b3a95213fb20889c7",
  "_rev": "1-34c1771f2108f6ad8efc0d99e79d78a0",
  "type": "ConstraintUnique",
  "docRef": "article::3808cea0-bb99-11e5-9ba4-315d40280ab9",
  "propertyName": "title",
  "propertyValue": "title1"
}

全部" ConstraintUnique "我拥有的文档" docRef "指向" _id "的字段实际的文档,如" Article._id "

3)。这样,如果我想在将来添加更多独特约束,我将添加另一个" ConstraintUnique "当我保存/创建新文章时,我会检查现有的约束文档"然后保存或拒绝原始文档。另一个选择是插入文档而不需要额外的"约束文档"并检查是否有重复使用视图并立即删除重复。 (所有内容都在这里描述:Unique constraints in couchdb)。

问题:

我正在进行实时双向复制(客户端到服务器和服务器到客户端同步),如下所示:

db.sync('remote db url', {
  live: true,
  retry: true
})

然后,我会听到这样的变化:

db.changes({
  since: 'now',
  live: true,
  include_docs: true,
  conflicts: true
}).on('change', function(change) {
  if (change.doc._conflicts) {
    // do coflict resolution
  }
});

我有以下情况,其中两个用户都处于脱机状态且没有数据同步到远程数据库,但是它被插入到本地数据库中:

1)。 User1处于离线状态,他将Articlename1title1一起插入,他的本地数据库将如下所示:

{
  "_id": "article--constraint-unique--name::e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
  "_rev": "1-de7e0636632764e97880f362d50598b7",
  "type": "ConstraintUnique",
  "docRef": "article::3808cea0-bb99-11e5-9ba4-315d40280ab9",
  "propertyName": "name",
  "propertyValue": "name1"
}

{
  "_id": "article--constraint-unique--title::5018e26faaec56a465e61aaeb752c2984c8a6d6305c8496b3a95213fb20889c7",
  "_rev": "1-34c1771f2108f6ad8efc0d99e79d78a0",
  "type": "ConstraintUnique",
  "docRef": "article::3808cea0-bb99-11e5-9ba4-315d40280ab9",
  "propertyName": "title",
  "propertyValue": "title1"
}

{
  "_id": "article::3808cea0-bb99-11e5-9ba4-315d40280ab9",
  "_rev": "1-8b8076d3fef9994ca65a516532c5f975"
  "type": "Article",
  "name": "name1",
  "title": "title1",
  "owner": "user1"
}

2)。 User2也处于离线状态,他正在使用Articlename1插入相同的title1,因此他的本地数据库看起来几乎相同,但Article._id不同以及相同的ConstraintUnique ids:

Same as User1's (except _rev and docRef):
{
  "_id": "article--constraint-unique--name::e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
  "_rev": "1-5c427cba5efe71114acb7e6ddd8b8a23",
  "type": "ConstraintUnique",
  "docRef": "article::ad16f2e4-9cff-42ae-ae92-27e353e7f229",
  "propertyName": "name",
  "propertyValue": "name1"
}

Same as User1's (except _rev and docRef):
{
  "_id": "article--constraint-unique--title::5018e26faaec56a465e61aaeb752c2984c8a6d6305c8496b3a95213fb20889c7",
  "_rev": "1-14244246dbbac7e55e132abe47fe115d",
  "type": "ConstraintUnique",
  "docRef": "article::ad16f2e4-9cff-42ae-ae92-27e353e7f229",
  "propertyName": "title",
  "propertyValue": "title1"
}

Different, but the actual data is the same:
{
  "_id": "article::ad16f2e4-9cff-42ae-ae92-27e353e7f229",
  "_rev": "1-8b8076d3fef9994ca65a516532c5f975"
  "type": "Article",
  "name": "name1",
  "title": "title1",
  "owner": "user2"
}

3)。实际问题:

User 1重新联机并且他的更改与远程数据库同步而没有冲突时:

Ids of the docs:
"_id": "article--constraint-unique--name::e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
"_id": "article--constraint-unique--title::5018e26faaec56a465e61aaeb752c2984c8a6d6305c8496b3a95213fb20889c7"
"_id": "article::3808cea0-bb99-11e5-9ba4-315d40280ab9"

稍后,User 2也重新联机,他的更改与远程数据库同步发生冲突:

Ids of the docs:
"_id": "article--constraint-unique--name::e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" -- conflicting with the User1
"_id": "article--constraint-unique--title::5018e26faaec56a465e61aaeb752c2984c8a6d6305c8496b3a95213fb20889c7" -- conflicting with the User1
"_id": "article::ad16f2e4-9cff-42ae-ae92-27e353e7f229" -- no conflict, but I need to remove this duplicate somehow

因此,CouchDB / Couchbase Sync Gateway选择获胜者&#34; 文章 - 约束 - 唯一 - 名称:: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 &#34;和&#34; 文章 - 约束 - 唯一 - 标题:: 5018e26faaec56a465e61aaeb752c2984c8a6d6305c8496b3a95213fb20889c7 &#34;在服务器端,但客户端上的PouchDB也同步重复的文章文档 - 我想清理约束文档冲突(&#34; 文章 - 约束 - 唯一 - 名称:: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 & #34;和&#34; 文章 - 约束 - 唯一 - 标题:: 5018e26faaec56a465e61aaeb752c2984c8a6d6305c8496b3a95213fb20889c7 &#34;)并更新 docRef (如果 docRef < / strong>在&#34; 名称&#34;以及&#34; 标题&#34;约束)上不一样,我也想删除带有ids &#34; article :: 3808cea0-bb99-11e5-9ba4-315d40280ab9&#34;(User1)&#34; article :: ad16f2e4-9cff-42ae的重复文章-ae92-27e353e7f229&#34;(User2)或更好我想选择一篇获奖文章,然后在&#34; 文章 - 约束 - 唯一中更新 docRef 强>&#34;文档。欢迎任何解决方案 - 我只想删除重复的文章和更新约束占位符以与获胜文章同步。

我已经完成了原始实施,我在更改Feed http://pouchdb.com/guides/changes.html)中检查了冲突,我正在使用 Ionic 1 / AngularJS 1 + PouchDB 并尝试删除重复的doc / Article:

var changeListener = db.changes({
  since: 'now',
  live: true,
  include_docs: true,
  conflicts: true
}).on('change', function(change) {
  var doc = angular.copy(change.doc);
  var i;

  if (doc._conflicts) {
    if (doc.type && (doc.type === 'ConstraintUnique')) {
      for (i = 0; i < doc._conflicts.length; i++) {
        (function(currentConflictRev) {
          // get conflicted "ConstraintUnique"
          db.get(doc._id, {rev: currentConflictRev}).then(function(conflictConstraintUniqueDoc) {
            if (conflictConstraintUniqueDoc.docRef) {
              // get linked to "ConstraintUnique" doc and delete it
              db.get(conflictConstraintUniqueDoc.docRef)
                .then(function(conflictDoc) {
                  // delete the duplicated doc
                  db.remove(conflictDoc._id, conflictDoc._rev);
                  // resolve the current conflict
                  db.remove(conflictConstraintUniqueDoc._id, conflictConstraintUniqueDoc._rev);
                });
            }
          });
        })(doc._conflicts[i]);
      }
    }
  }
});

当Couch服务器决定赢得&#34; ConstraintUnique &#34;时,此实现无效。 名称的文档是 docRef == user1Article ,另一个获胜&#34; ConstraintUnique &#34; 标题的文档与 docRef == user2Article 一起使用 - 这样两种文章都会被删除,而不仅仅是重复的文章。

我确定,我做错了:所以,如何处理冲突和离线客户端同步我们在其字段中使用具有唯一约束的文档,以防最终发生冲突/主 - 主冲突?

在解决方案上阅读更多主题并没有运气:

非常感谢你!

0 个答案:

没有答案