当数组对象的位置之一改变时,如何按位置求位?

时间:2018-09-11 11:34:40

标签: javascript node.js mongodb

期望的行为

当对象的位置之一改变时,我正在尝试更新对象数组中每个对象的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应该增加(除   被移动的对象,应为其指定new_position)

     

如果reposition_direction向前,则所有具有位置的对象   小于或等于new_position的值应减小(除   要移动的对象,应为其分配new_position)

update :此逻辑不正确,已添加工作逻辑以回答)

这是我到目前为止所拥有的:

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 :(得分:0)

每次更改数组时,都要在其每个成员上设置位置:

for (var i = 0; i < statements.length; i++) {
    statements[i].position = i;
}

答案 1 :(得分:0)

有人建议更好的主意是获取数组,遍历结果,然后设置整个数组的值,但是我很想知道是否可以正确地执行排序逻辑,我认为以下作品。只需粘贴下面以供参考。

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