【问题标题】:MongoDb: $inc multiple documents with unique indexMongoDb:$inc 具有唯一索引的多个文档
【发布时间】:2016-12-15 16:56:36
【问题描述】:

我有以下代码:

db.foo.insert([{_pos:1,b:12},{_pos:2,a:23},{_pos:3,c:12}])
db.foo.createIndex( { "_pos" : 1 }, { unique:  true } )
db.foo.update({}, { "$inc" : {"_pos" : 1} }, { multi : true })

最后一行给了我以下错误:

E11000 重复键错误索引:JsonTableTemp.foo.$_pos_1 重复键:{ : 2.0 }

$isolated 添加到查询中没有帮助。

如何在不先删除索引的情况下增加 _pos 字段?

我使用 mongodb 3.2.6

【问题讨论】:

  • 我刚试过这个,createIndex 为我抛出了错误。当我从第二行删除 { unique: true } 时,更新实际上运行良好。
  • @dyouberg:为什么 createIndex 失败了?你用的是哪个mongodb版本?
  • Mongo 版本 3.2.0 > db.foo.createIndex( { "_pos" : 1 }, { unique: true } ) { "ok" : 0, "errmsg" : "E11000 重复密钥错误集合:test.foo 索引:_pos_1 复制键:{ : 1.0 }", "code" : 11000 }
  • 这怎么可能?你确定你的集合是空的并且真的只包含 3 个文档吗?
  • 嗯,你是对的,我想我复制粘贴了第一行两次。我有 6 个条目。我刚刚又试了一次,得到了和你一样的结果。让我仔细看看。

标签: mongodb


【解决方案1】:

好的,我明白了……

由于您要使索引唯一 - 这些值永远不能共享相同的值。值为 [1,2,3]。 increment 是 MongoDB 的原子操作,因此它们一次发生一个......首先是 [2,2,3],然后是 [2,3,3],最后是 [2,3,4]。

为了证明这一点...只需将值反转为 [3,2,1] 即可开始。

> db.foo5.insert([{_pos:3,b:12},{_pos:2,a:23},{_pos:1,c:12}])
BulkWriteResult({
    "writeErrors" : [ ],
    "writeConcernErrors" : [ ],
    "nInserted" : 3,
    "nUpserted" : 0,
    "nMatched" : 0,
    "nModified" : 0,
    "nRemoved" : 0,
    "upserted" : [ ]
})
> db.foo5.createIndex( { "_pos" : 1 }, { unique:  true } )
{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 2,
    "ok" : 1
}
> db.foo5.find()
{ "_id" : ObjectId("57a9f76cb28f053d25a821a5"), "_pos" : 3, "b" : 12 }
{ "_id" : ObjectId("57a9f76cb28f053d25a821a6"), "_pos" : 2, "a" : 23 }
{ "_id" : ObjectId("57a9f76cb28f053d25a821a7"), "_pos" : 1, "c" : 12 }
> db.foo5.update({}, { "$inc" : {"_pos" : 1} }, { multi : true })
WriteResult({ "nMatched" : 3, "nUpserted" : 0, "nModified" : 3 })
> db.foo5.find()
{ "_id" : ObjectId("57a9f76cb28f053d25a821a5"), "_pos" : 4, "b" : 12 }
{ "_id" : ObjectId("57a9f76cb28f053d25a821a6"), "_pos" : 3, "a" : 23 }
{ "_id" : ObjectId("57a9f76cb28f053d25a821a7"), "_pos" : 2, "c" : 12 }

【讨论】:

  • 是的,我也发现了这一点,但是更改顺序对我来说并不是一个真正的选择。这就是为什么我问:我怎样才能增加 _pos 字段而不首先删除索引?
  • 是的,看起来要么必须删除索引的唯一部分,要么需要对操作应用某种形式的并发控制。我也尝试了 $isolated 并且无法使其正常工作。您的索引是否需要唯一?
  • 如果我去掉唯一的部分,我必须确保客户端的唯一性,这感觉不对。另外我认为与普通索引相比,唯一索引会加快一些操作。
  • 那么我们要么需要找到一种方法以非原子方式执行增量,要么需要在调用更新之前按降序对数据进行预排序。这两者都会增加开销。我尝试了 findAndModify 和 $isolated 但它们都不起作用。 $isolated 仅在文档​​级别工作,并锁定文档以防止第二次操作,因此我认为它不适用于此处。
猜你喜欢
  • 2017-08-16
  • 2016-03-15
  • 1970-01-01
  • 2014-02-23
  • 2016-01-18
  • 2020-10-10
  • 1970-01-01
  • 1970-01-01
  • 2013-07-28
相关资源
最近更新 更多