Необходимо обновить одним запросом несколько данных. Вот пример запроса:
db.coll.update(
{ article: 100500 },
{
$set: { a: 555 },
$pull: { arr: { t: { $lt: 20 } } }
}
);
А вот пример самого документа:
{
article: 100500,
a: 400,
arr: [
{ t: 30, b: 12, n: 90 },
{ t: 10, b: 16, n: 60 }
]
}
Мой запрос:
Обновляет значение a на 555
Удаляет все элементы массива arr, где t < 20
Суть вопроса:
Надо обновить значения b в маccве arr. То есть, везде где n == 90, значение b надо поменять на 777. Как можно дополнить этот запрос, чтобы "убить сразу 3-х зайцев"?
В итоге должен получиться такой документ:
{
article: 100500,
a: 555, /* Тут было: 400 */
arr: [
{ t: 30, b: 777, n: 90 },
/* Тут был элемент массива */
]
}
Ответ
Я полагаю, у вас есть следующие документы в вашей коллекции.
{
"_id" : ObjectId("56b71025973d202a52a5e650"),
"article" : 100500,
"a" : 400,
"arr" : [
{ "t" : 30, "b" : 12, "n" : 90 },
{ "t" : 20, "b" : 16, "n" : 60 }
]
},
{
"_id" : ObjectId("56b7102b973d202a52a5e651"),
"article" : 100500,
"a" : 400,
"arr" : [
{ "t" : 0, "b" : 12, "n" : 90 },
{ "t" : 10, "b" : 16, "n" : 60 }
]
},
{
"_id" : ObjectId("56b710d4973d202a52a5e652"),
"article" : 100500,
"a" : 400,
"arr" : [
{ "t" : 30, "b" : 12, "n" : 90 },
{ "t" : 27, "b" : 16, "n" : 32 }
]
}
Прежде всего вы должны знать, что это не возможно, чтобы обновить более одного элемента в массиве используя метод update() даже с опцей multi: true или используя метод updateMany(); и все логики позади, что вы пытаетесь сделать; делать вещи более сложнее.
Лучший способ это делать это используя Bulk Операции
Решение для MongoDB версия 3.2 или новее:
MongoDB 3.2 не рекомендуется Bulk() и связанные с ним методы. Нужно использовать метод .bulkWrite()
Здесь у нас есть два варианта:
Нужно использовать агрегация чтотбы уменшать количество докуменьов которые нужно обновить. здесь в цепочке нужно только один этап: $project где мы используем оператор $filter
let requests = [];
db.collection.aggregate([
{ "$project": {
"deleteElements": {
"$filter": {
"input": "$arr",
"as": "del",
"cond": { "$lt": [ "$$del.t", 12 ] }
}
},
"updateElements": {
"$filter": {
"input": "$arr",
"as": "upd",
"cond": {
"$and": [
{ "$gte": [ "$$upd.t", 12 ] },
{ "$eq": [ "$$upd.n", 90 ] }
]
}
}
}
}}
]).forEach(function(document) {
document.deleteElements.forEach(function(element) {
requests.push(
{
"updateOne": {
"filter": {
"_id": document._id,
"arr.t": element.t
},
"update": { "$pull": { "arr": element } }
}
}
);
});
document.updateElements.forEach(function(element) {
requests.push(
{
"updateOne": {
"filter": {
"_id": document._id,
"arr.t": element.n
},
"update": { "$set": { "arr.$.b": 777 } }
}
}
);
});
requests.push(
{
"updateOne": {
"filter": { "_id": document._id },
"update": { "$set": { "a": 555 } }
}
}
);
})
db.collection.bulkWrite(requests)
Используя метод .find()
db.collection.find({"article": 100500}).snapshot().forEach(function(document) {
document.arr.filter(function(arr) {
return arr.t < 12;
}).forEach(function(element) {
requests.push(
{
"updateOne": {
"filter": {
"_id": document._id,
"arr.t": { "$lt": 12 }},
"update": { "$pull": { "arr": element } }
}
}
);
});
document.arr.filter(function(arr) {
return arr.n === 90;
}).forEach(function(element) {
requests.push(
{
"updateOne": {
"filter": { "_id": document._id, "arr.n": 90 },
"update": { "$set": { "arr.$.b": 777 } }
}
}
);
});
requests.push(
{
"updateOne": {
"filter": { "_id": document._id },
"update": { "$set": { "a": 555 } }
}
}
);
})
db.collection.bulkWrite(requests);
Решение для MongoDB версии 2.6 или новее:
var bulk = db.collection.initializeOrderedBulkOp();
var count = 0;
db.collection.find({"article": 100500}).snapshot().forEach(function(document) {
document.arr.filter(function(arr) {
return arr.t < 12;
}).forEach(function(element) {
bulk.find({ "_id": document._id, "arr.t": { "$lt": 12 } } ).updateOne({
"$pull": { "arr": element }
});
count++;
});
document.arr.filter(function(arr) {
return arr.n === 90;
}).forEach(function(element) {
bulk.find({ "_id": document._id, "arr.n": 90 }).updateOne({
"$set": { "arr.$.b": 777 }
});
count++;
});
bulk.find( { "_id": document._id } ).updateOne( { "$set": { "a": 555 } } );
count++;
if (count % 1000 === 0) {
// Выпольнить после 1000 операции
bulk.execute();
bulk = db.collection.initializeOrderedBulkOp();
}
})
// Очистить очереди
if (count > 0) { bulk.execute(); }
Результать
{
"_id" : ObjectId("56b71025973d202a52a5e650"),
"article" : 100500,
"a" : 555,
"arr" : [
{ "t" : 30, "b" : 777, "n" : 90 },
{ "t" : 20, "b" : 16, "n" : 60 }
]
}
{
"_id" : ObjectId("56b7102b973d202a52a5e651"),
"article" : 100500,
"a" : 555,
"arr" : [ ]
}
{
"_id" : ObjectId("56b710d4973d202a52a5e652"),
"article" : 100500,
"a" : 555,
"arr" : [
{ "t" : 30, "b" : 777, "n" : 90 },
{ "t" : 27, "b" : 16, "n" : 32 }
]
}
Комментариев нет:
Отправить комментарий