Среда
Родной драйвер Node
MongoDB 4.0.2
Желаемое поведение
Удалите объект из массива объектов на основе его id
и уменьшите значение position
другого объекта, где это возможно.
В частности, я пытаюсь:
iterate over an array of objects in MongoDB and update a property in each object
Возможно, это может быть связано с использованием $inc
и -1
, но я все еще не уверен, как выполнить итерацию.
Что я пробовал
У меня есть логика, работающая для сценария JavaScript
(работает в консоли браузера):
function remove_and_update_position(id) {
// faux array in collection document
var statements = [{
position: 0, // < i want to update 'position' of all objects after an object is removed
id: "a"
},
{
position: 1,
id: "b"
},
{
position: 2,
id: "c"
},
{
position: 3,
id: "d"
},
{
position: 4,
id: "e"
}
];
// delete an object from the 'statements' array by its id
statements.splice(statements.indexOf(statements.find(item => item.id == id)), 1);
// iterate over the modified array
for (var i = 0; i < statements.length; i++) {
// for all objects in the modified array,
// with position numbers greater than the
// position removed ( minus 1),
// decrement their position numbers
if (i > position - 1) {
var new_position = statements[i].position - 1;
statements[i].position = new_position;
}
}
// verify adjustments were correct
console.info(statements);
}
// call the function
remove_and_update_position("c");
Мне просто нужно перевести это в сценарий MongoDB/Node
- пока у меня есть только часть удаления объекта:
const remove_and_update_position = (req, res) => {
var request_body = req.body;
var topic_id = request_body.topic_id;
var o_id = new ObjectID(topic_id);
var collection = mongo_client.db("topics").collection("topics");
var statement_id = request_body.statement_id;
var position = Number(request_body.position);
// query for the relevant document *and* target nested statement by id
var filter = { _id: o_id, "statements.id": statement_id };
// remove from statements array
var update = { $pull: { "statements": { id: statement_id } } };
// perform the update
collection.updateOne(filter, update, function(err, doc) {
if (err) {
res.send(err);
} else {
res.json({ response_type: "success" });
}
});
}
Обновлено согласно ответь здесь.
const remove_and_update_position = (req, res) => {
var request_body = req.body;
var topic_id = request_body.topic_id;
var o_id = new ObjectID(topic_id);
var collection = mongo_client.db("topics").collection("topics");
var statement_id = request_body.statement_id;
var position = Number(request_body.position);
// query for the relevant document *and* target nested statement by id
var filter = { _id: o_id, "statements.id": statement_id };
// remove from statements array
var update = { $pull: { "statements": { id: statement_id } } };
// perform the update
collection.updateOne(filter, update, function(err, doc) {
if (err) {
res.send(err);
} else {
// BEGIN decrement others objects position
var position_indicator = position - 1;
console.info("deleted object position: " + position);
console.info("will decrement objects with position greater than: " + position_indicator);
var new_filter = { _id: o_id, "statements.position": { $gt: position_indicator } };
var new_update = { $inc: { "statements.$[elem].position": -1 } };
var array_filters = { "arrayFilters": [{ "elem.position": { $gt: position_indicator } }], "multi": true };
collection.updateOne(new_filter, new_update, array_filters, function(err, doc) {
if (err) {
res.send(err);
} else {
res.json({ response_type: "success" });
}
});
// END decrement others objects position
}
});
}
Хм, я думаю, это обновление только одного объекта в массиве statements
. updateMany () документы говорит об этом методе updates multiple documents within the collection based on the filter
. Так что, возможно, это неправильный метод, поскольку он, похоже, не обновляет несколько объекты в массиве. Может мне просто надо сделать какой нибудь стандартный update()
, где какой то multi
определяется как true? Однако этот ответ делает вид, что это невозможно? : /
Хм, похоже, это заставляет запрос игнорировать $gt
, и у объектов все обновлена их позиция (даже объект в позиции 0
изменяется на позицию -1
, если объект в позиции 2
удален). Сейчас я смотрю на этот обновленный ответ: stackoverflow.com/a/46054172 ... обновил ваш ответ тем, что у меня работает.
Должно ли свойство
position
вupdateMany
быть чем-то вроде:statements.position
? Потому что объект вложен в массивstatements
?