2016-08-09 3 views
3

У меня есть следующий код:

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 duplicate key error index: JsonTableTemp.foo.$_pos_1 dup key: { : 2.0 }

Добавление $isolated на запрос не поможет ,

Как я могу увеличить поле _pos, не отбрасывая индекс первым?

Я использую MongoDB 3.2.6

+0

Я просто попробовал это, и createIndex выбросил ошибку для меня. Обновление действительно отлично работало, когда я удалил {unique: true} со второй строки. – dyouberg

+0

@dyouberg: Почему createIndex не удалось? Какую версию mongodb вы используете? – Dreamcooled

+0

Монго Version 3.2.0 > db.foo.createIndex ({ "_pos": 1}, {уникальный: истинный}) { \t "ОК": 0, \t "ErrMsg": «E11000 дубликат ключа ошибки коллекция: test.foo index: _pos_1 dup key: {: 1.0} ", \t" код ": 11000 } – dyouberg

ответ

2

Хорошо я получил его ...

Поскольку вы делаете индексы уникальным - значения не могут когда-либо одни и те же значения. Значения: [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 } 
+0

Да, я тоже это выяснил, но изменение заказа для меня не является для меня вариантом. Вот почему я спросил: как я могу увеличивать поле _pos ** без ** сначала отбрасывая индекс? – Dreamcooled

+0

Да, похоже, что либо уникальная часть индекса должна быть удалена, либо какая-то форма контроля параллелизма должна применяться к операции. Я тоже пытался изолировать $ и не мог заставить это работать. Есть ли причина, по которой ваш индекс должен быть уникальным? – dyouberg

+0

Если я удалю уникальную часть, я должен обеспечить уникальность клиентской стороны, которая кажется неправильной. Также я думаю, что уникальный индекс ускорит некоторые операции по сравнению с обычным индексом. – Dreamcooled

Смежные вопросы