Умножить поле на значение в Mongodb - PullRequest
29 голосов
/ 01 декабря 2011

Я искал способ создать оператор обновления, который будет принимать существующее числовое поле и изменять его с помощью выражения. Например, если у меня есть поле с именем Price, возможно ли выполнить обновление, в котором для Price будет установлено значение 50% от существующего значения?

Итак, учитывая { Price : 19.99 }

Я бы хотел сделать db.collection.update({tag : "refurb"}, {$set {Price : Price * 0.50 }}, false, true);

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

Ответы [ 4 ]

37 голосов
/ 01 декабря 2011

Вы можете запустить серверный код с помощью db.eval().

db.eval(function() { 
    db.collection.find({tag : "refurb"}).forEach(function(e) {
        e.Price = e.Price * 0.5;
        db.collection.save(e);
    });
});

Обратите внимание, что это заблокирует БД, поэтому лучше создать пару операций поиска-обновления.1007 *https://docs.mongodb.com/manual/core/server-side-javascript/

21 голосов
/ 07 ноября 2013

В новом Mongo 2.6.x есть оператор $ mul .Это умножит значение поля на число со следующим синтаксисом.

{
  $mul: { field: <number> }
}

Так что в вашем случае вам нужно будет сделать следующее:

db.collection.update(
  { tag : "refurb"},
  { $mul: { Price : 0.5 } }
);
0 голосов
/ 12 июня 2019

Начиная с Mongo 4.2, db.collection.update() можно принять конвейер агрегации, наконец, разрешив обновление поля на основе другого поля:

// { price: 19.99 }
// { price: 2.04  }
db.collection.update(
  {},
  [{ $set: { price: { $multiply: [ 0.5, "$price" ] } } }],
  { multi: true }
)
// { price: 9.995 }
// { price: 1.02  }
  • Первая часть {} - это запрос на совпадение, отфильтровывающий, какие документы нужно обновить (в данном случае все документы).

  • Вторая часть [{ $set: { price: ... } }] - это конвейер агрегации обновлений (обратите вниманиеквадратные скобки, обозначающие использование конвейера агрегации).$set - новый оператор агрегирования и псевдоним $addFields.Обратите внимание, как price изменяется непосредственно на основе его собственного значения ($price).

  • Не забудьте { multi: true }, иначе будет обновлен только первый соответствующий документ.

0 голосов
/ 01 декабря 2011

Ну, это возможно с атомарной операцией как $ set.

У вас есть несколько вариантов:

  • используйте решение eval (), предложенное pingw33n
  • получить документ, который вы хотите изменить, чтобы получить текущее значение, и изменить его с помощью набора
  • если у вас высокая скорость работы, вы можете быть уверены, что фокус не изменился во время извлечения его значения (с использованием предыдущего решения), поэтому вы можете использовать findAndModify (см. эту страницу чтобы получить вдохновение о том, как это сделать) операция.

Это действительно зависит от вашего контекста: при очень низком давлении на БД я бы пошел на решение pingw33n. С очень высокой скоростью работы я бы использовал третье решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...