Как прибегнуть к массиву объектов по позиции, когда одна из их позиций изменяется? - PullRequest
0 голосов
/ 11 сентября 2018

Желаемое поведение

Я пытаюсь обновить свойство position каждого объекта в массиве объектов при изменении одной из их позиций. Например, объект с позицией 5 перемещается в позицию 0, поэтому позиции других объектов также должны меняться.

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

Схема

statements: [
{
    "position": 0,
    "id": "a"
},
{
    "position": 1,
    "id": "t"
},
{
    "position": 2,
    "id": "z"
},
{
    "position": 3,
    "id": "q"
},
{
    "position": 4,
    "id": "l"
},
{
    "position": 5,
    "id": "b"
}
]

Сценарий внешнего интерфейса

Figure A: Starting state of ordered divs
enter image description here

Figure B: Changed state of ordered divs (statement 5 has been moved to position 0 )
enter image description here

Что я пробовал

Псевдокод

Я думаю, что логика может быть выражена как:

Положение объектов изменится от old_position к new_position на произвольное количество мест.

Если reposition_direction задом наперед, все объекты с положением больше или равно new_position, должно увеличиваться (кроме перемещаемый объект, которому должна быть назначена новая_позиция)

Если reposition_direction вперед, все объекты с положением меньше или равно new_position должно уменьшаться (кроме перемещаемый объект, которому должна быть назначена новая_позиция)

( обновление : эта логика неверна, рабочая логика добавлена ​​в ответ)

Это то, что у меня есть до сих пор:

if (reposition_direction === "backwards") {

    var new_filter = { _id: o_id, "statements.position": { $gte: new_position } };

    var new_update = { $inc: { "statements.$[elem].position": 1 } };

    var array_filters = { "arrayFilters": [{ "elem.position": { $gte: new_position } }], "multi": true };

} else if (reposition_direction === "forwards") {

    var new_filter = { _id: o_id, "statements.position": { $lte: new_position } };

    var new_update = { $inc: { "statements.$[elem].position": -1 } };

    var array_filters = { "arrayFilters": [{ "elem.position": { $lte: new_position } }], "multi": true };
}

collection.updateOne(new_filter, new_update, array_filters, function(err, doc) {
    if (err) {
        res.send(err);
    } else {
        res.json({ response: "hurrah" });
    }
});

Ответы [ 2 ]

0 голосов
/ 11 сентября 2018

Было высказано предположение, что лучшей идеей было бы просто получить массив, выполнить итерацию по результату, а затем установить значение всего массива, но я был заинтригован, чтобы посмотреть, смогу ли я получить правильную логику сортировки, и я думаю, что следующие работы. Просто вставьте ниже для справки.

var new_position = Number(request_body.new_position);
var old_position = Number(request_body.old_position);
var reposition_direction = request_body.reposition_direction;
var statement_id = request_body.statement_id;
var filter = { _id: o_id };

if (reposition_direction === "backwards") {

    // if backwards, position filter is $gte new_position AND $lt old_position
    var new_filter = { _id: o_id, "statements.position": { $gte: new_position, $lt: old_position } };

    // increment
    var new_update = { $inc: { "statements.$[elem].position": 1 } };

    var array_filters = { "arrayFilters": [{ "elem.position": { $gte: new_position, $lt: old_position } }], "multi": true };

} else if (reposition_direction === "forwards") {

    // if forwards, position filter is $lte new_position AND $gt old_position
    var new_filter = { _id: o_id, "statements.position": { $lte: new_position, $gt: old_position } };

    // decrement
    var new_update = { $inc: { "statements.$[elem].position": -1 } };

    var array_filters = { "arrayFilters": [{ "elem.position": { $lte: new_position, $gt: old_position } }], "multi": true };

}

collection.updateOne(new_filter, new_update, array_filters, function(err, doc) {
    if (err) {
        res.send(err);
    } else {

        // set the moved objects property to the new value
        var new_filter = { _id: o_id, "statements.id": statement_id };
        var new_update = { $set: { "statements.$.position": new_position } };

        collection.findOneAndUpdate(new_filter, new_update, function(err, doc) {
            if (err) {
                res.send(err);
            } else {
                res.json({ response: "hurrah" });
            }
        });
    }
});

Вызов обработчика успеха на findOneAndUpdate() был вдохновлен этим ответом:

https://stackoverflow.com/a/30387038

Я проверил следующие комбинации, и они, кажется, работают:

Переместить 1 в 4
переместить 4 в 1

переместить 0 в 5
переместить 5 в 0

переместить 1 в 2
переместить 2 в 1

переместить 0 в 1
переместить 1 в 0

переместить 4 в 5
переместить 5 в 4

0 голосов
/ 11 сентября 2018

Каждый раз, когда вы меняете свой массив, устанавливайте позицию для каждого из его элементов:

for (var i = 0; i < statements.length; i++) {
    statements[i].position = i;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...