Первое, что нужно отметить, что пример вы даете не массив, а просто суб-документ для «плодов», который имеет разные ключи. «Массив» в MongoDB будет выглядеть следующим образом:
{ "fruits": [{ "apples":2 } , { "orange":3 }], "carrot": 5 }
Кроме того, в стороне от термина «фрукты» субъективны, так как нет другого идентификатора вы должны указать «список» вещей, которые квалифицируются как фрукты , другая вещь, которую следует учитывать, заключается в том, что в настоящее время в MongoDB нет реального способа ссылаться на существующее значение поля при обработке обновления.
Что это значит, вам нужно, чтобы каждый документ извлекал данные, чтобы иметь возможность работать с подобной «переструктурой», которую вы хотите. Это, по существу, означает объединение результатов, выполняющих операцию .update()
для каждого документа.
Bulk API для MongoDB 2.6 и выше, может иметь некоторую помощь здесь, где по крайней мере, «писать» операции в базе данных могут быть отправлены в пакетах, а не один, в то время:
var bulk = db.collection.initializeOrderedBulkOp();
var count = 0;
var fruits = ["apples","oranges"];
var unset = {};
fruits.forEach(function(fruit) {
unset[fruit] = 1;
});
db.collection.find({}).forEach(function(doc) {
var fields = [];
fruits.forEach(function(fruit) {
if (doc.hasOwnProperty(fruit)) {
var subDoc = {};
subDoc[fruit] = doc[fruit];
fields.push(subDoc);
}
});
bulk.find({ "_id": doc._id }).updateOne({
"$unset": unset, "$push": { "fruits": { "$each": fields } }
});
count++;
if (count % 1000 == 0) {
bulk.execute();
var bulk = db.collection.initializeOrderedBulkOp();
}
});
if (count % 1000 != 0)
bulk.execute();
Это также использует модификатор $each
для $push
, чтобы добавить сразу несколько записей массива. Оператор $unset
может быть безопасно вызван для полей, которые не существуют в документе, поэтому нет необходимости проверять их присутствие в документе, как это требуется при построении массива элементов до $push
.
Конечно, если вы на самом деле хотите, документ, как то, что вы дали пример того, что это на самом деле не является массивом, то вы строите по-разному с $set
оператора:
var fields = {};
fruits.forEach(function(fruit) {
if (doc.hasOwnProperty(fruit))
fields[fruit] = doc[fruit];
});
bulk.find({ "_id": doc._id }).updateOne({
"$unset": unset, "$set": { "fruits": fields }
});
В любом случае это нужно цикл существующей коллекции. Нет операции, позволяющей «взять» существующее значение в документе и «использовать его», чтобы установить новое значение с точки зрения сервера.
Не могли бы вы лучше объяснить, что делать? Потому что я не понимаю, почему вы говорите о массиве. Я вижу только список документов. Спасибо – MetalMad
Что мне нужно, чтобы принести все фрукты под общим ключом Фрукты в качестве вспомогательного документа. – pjsuccess