2014-02-20 1 views
1

Если у меня есть документ, который выглядит, как это, например:Подавать поля в MongoDB документе

{ 
    "a" : "val", 
    "b" : "another val" 
} 

Как я могу флип указанного поля так, что результат выглядит

{ 
    "b" : "val", 
    "a" : "another val" 
} 

Я пробовал db.collection.update({}, {$rename:{'a':'b', 'b':'a'}}), но я получаю ошибку Field name duplication not allowed with modifiers

ответ

3

Это классическая проблема с тазобедренным монетом. Вероятно, то, что вам не хватает в вышесказанном, заключается в том, что вы всегда столкнетесь с тем, что при создании этого обновления за 1 шаг указали тот же самый field. Вы должны будете сделать это в несколько этапов, так что логично:

db.collection.update({}, {$rename: { 'a': 'c' }}) 
db.collection.update({}, {$rename: { 'b': 'a' }}) 
db.collection.update({}, {$rename: { 'c': 'b' }}) 

Но мы можем сделать лучше, и избежать столкновения в двух шагах

db.collection.update({}, {$rename:{ 'a': 'c', 'b': 'd' }}) 
db.collection.update({}, {$rename:{ 'c': 'b', 'd': 'a' }}) 

Конечно, это не одна операция, и это не так просто и no вы не можете ссылаться на значение другого поля и обновлять его до другого.

И, конечно же, делайте это только там, где вам действительно необходимо изменить названия полей. Страница руководства $rename охватывает варианты использования. Если вы просто хотите видеть вещей таким образом, просто $project форму вы хотите:

db.collection.aggregate([{$project: { a: "$b", b: "$a" }}]) 
-1

Стоит отметить, что с новыми операциями насыпного обновления приходят в MongoDB 2.6 можно сделать это переименование в одной операции на стороне сервера. На момент публикации 2.6 все еще находится в предварительном рассмотрении; вы можете проверить MongoDB download page на наличие. Для получения полного списка изменений и новых функций просмотрите release notes.

Вот Монго синтаксис оболочки для выполнения этого поля переименования в одной команде на стороне сервера:

var bulk = db.c.initializeOrderedBulkOp(); 
bulk.find({}).update({$rename: {a:'tmp'}}) 
bulk.find({}).update({$rename: {b:'a'}}) 
bulk.find({}).update({$rename: {tmp:'b'}}) 
bulk.execute() 
+0

Не могу видеть, как это помогает на этот вопрос. Это одно обновление документа, как было указано. Возможно, это ** примечание ** принадлежит другому. –

+0

Для конкретного вопроса, заданного здесь, преимущество действительно тривиально - одно круговое путешествие к серверу против двух. Для других приложений, которые могли бы использовать представленные здесь решения, экономия в обратном направлении к серверу для каждого переименованного поля может представлять интерес. –