Подтвердить что ты не робот

MongoDB: Обновление документов с использованием данных из того же документа

У меня есть список документов, каждый из которых имеет свойства lat и lon (среди прочих).

{ 'lat': 1, 'lon': 2, someotherdata [...] } 
{ 'lat': 4, 'lon': 1, someotherdata [...] }
[...]

Я хочу изменить его так, чтобы он выглядел так:

{ 'coords': {'lat': 1, 'lon': 2}, someotherdata [...]} 
{ 'coords': {'lat': 4, 'lon': 1}, someotherdata [...]}
[...]

Пока у меня есть это:

db.events.update({}, {$set : {'coords': {'lat': db.events.lat, 'lon': db.events.lon}}}, false, true)

Но он рассматривает db.events.lat и db.events.lon как строки. Как я могу ссылаться на свойства документа?

Приветствия.

4b9b3361

Ответ 1

Оператор $rename (введенный через месяц после того, как этот вопрос был отправлен) позволяет очень легко делать такие вещи, t необходимо изменить значения.

Вставить несколько тестовых документов

db.events.insert({ 'lat': 1, 'lon': 2, someotherdata: [] })
db.events.insert({ 'lat': 4, 'lon': 1, someotherdata: [] })

используйте оператор $rename

db.events.update({}, {$rename: {'lat': 'coords.lat', 'lon': 'coords.lon'}}, false, true)

Результаты

db.events.find()
{
    "_id" : ObjectId("5113c82dd28c4e8b79971add"),
    "coords" : {
        "lat" : 1,
        "lon" : 2
    },
    "someotherdata" : [ ]
}
{
    "_id" : ObjectId("5113c82ed28c4e8b79971ade"),
    "coords" : {
        "lat" : 4,
        "lon" : 1
    },
    "someotherdata" : [ ]
}

Ответ 2

Обновление:. Если вам нужно всего лишь изменить структуру документа, не изменяя значения, см. gipset answer для приятного решение.


В соответствии с комментарием (теперь недоступным) на странице Обновить документацию вы не можете ссылаться на текущие свойства документа из update().

Вам придется перебирать все документы и обновлять их следующим образом:

db.events.find().snapshot().forEach(
  function (e) {
    // update document, using its own properties
    e.coords = { lat: e.lat, lon: e.lon };

    // remove old properties
    delete e.lat;
    delete e.lon;

    // save the updated document
    db.events.save(e);
  }
)

Такая функция также может использоваться в задании сокращения карты или задании на стороне сервера db.eval(), в зависимости от ваших потребностей.

Ответ 3

Мы можем использовать Mongo script для управления данными "на лету". Это работает для меня!

Я использую этот script для исправления моих данных адреса.

Пример текущего адреса: "No.12, FIFTH AVENUE".

Я хочу удалить последнюю резервную запятую, ожидаемый новый адрес "№ 12, ПЯТЫЙ ПРОСВЕТ".

var cursor = db.myCollection.find().limit(100);

while (cursor.hasNext()) {
  var currentDocument = cursor.next();

  var address = currentDocument['address'];
  var lastPosition = address.length - 1;

  var lastChar = address.charAt(lastPosition);

  if (lastChar == ",") {

    var newAddress = address.slice(0, lastPosition);


    currentDocument['address'] = newAddress;

    db.localbizs.update({_id: currentDocument._id}, currentDocument);

  }
}

Надеюсь, это поможет!

Ответ 4

Ответы Neils. Просто, чтобы люди знали, что вы не можете запустить это в большой базе данных, если вы позволите сделать это удаленную оболочку, такую ​​как Robomongo. Вам понадобится ssh в ваш реальный сервер mongo shell. Также вы можете сделать это, если хотите сделать обновление.

db.Collection.find({***/ possible query /***}).toArray().forEach(
  function(obj){
    obj.item = obj.copiedItem;
    obj.otherItem = obj.copiedItem;
    obj.thirdItem = true;
    obj.fourthItem = "string";
    db.Collection.update({_id: obj._id}, obj);
  }
);

Ответ 5

Пока вы работаете с созданием копии данных, в качестве альтернативы можно использовать структуру агрегации. У вас также есть возможность сделать больше данных, если вы хотите использовать другие операторы, но вам нужен только $project. Это несколько расточительно с точки зрения пространства, но может быть более быстрым и более подходящим для некоторых целей. Чтобы проиллюстрировать это, я сначала вложу некоторые примеры данных в коллекцию foo:

db.foo.insert({ 'lat': 1, 'lon': 2, someotherdata : [1, 2, 3] })
db.foo.insert({ 'lat': 4, 'lon': 1, someotherdata : [4, 5, 6] })

Теперь мы просто используем $project для обработки полей lat и lon, а затем отправляем их в коллекцию newfoo:

db.foo.aggregate([
    {$project : {_id : "$_id", "coords.lat" : "$lat", "coords.lon" : "$lon", "someotherdata" : "$someotherdata" }},
    { $out : "newfoo" }
])

Затем проверьте newfoo на наши измененные данные:

db.newfoo.find()
{ "_id" : ObjectId("544548a71b5cf91c4893eb9a"), "someotherdata" : [ 1, 2, 3 ], "coords" : { "lat" : 1, "lon" : 2 } }
{ "_id" : ObjectId("544548a81b5cf91c4893eb9b"), "someotherdata" : [ 4, 5, 6 ], "coords" : { "lat" : 4, "lon" : 1 } }

После того как вы довольны новыми данными, вы можете использовать команду renameCollection(), чтобы удалить старые данные и использовать новую данные под старым именем:

> db.newfoo.renameCollection("foo", true)
{ "ok" : 1 }
> db.foo.find()
{ "_id" : ObjectId("544548a71b5cf91c4893eb9a"), "someotherdata" : [ 1, 2, 3 ], "coords" : { "lat" : 1, "lon" : 2 } }
{ "_id" : ObjectId("544548a81b5cf91c4893eb9b"), "someotherdata" : [ 4, 5, 6 ], "coords" : { "lat" : 4, "lon" : 1 } }

Последнее примечание - до завершения SERVER-7944 вы не можете сделать эквивалент моментального снимка, указав индекс _id как это предложено в этом ответе, и поэтому вы можете в конечном итоге ударить документ несколько раз, если активность в другом месте заставляет его двигаться. Поскольку вы вставляете поле _id в этом примере, любое такое возникновение может вызвать уникальное нарушение ключа, поэтому вы не будете обманываться, но у вас может быть "старая" версия документа. Как всегда, тщательно проверьте свои данные, прежде чем отбрасывать их, и, желательно, сделайте резервную копию.

Ответ 6

Из CLI? Я думаю, вам нужно сначала вывести значения и присвоить значение переменной. Затем запустите команду обновления.

Или (я еще не пробовал) удаляю 'db' из строки. events.lat и events.lon Если это сработает, вы все равно будете иметь несколько значений, старые значения для "lat" и "lon" и новый массив, который вы создали.