Jonathan Nielsen Jonathan Nielsen - 3 months ago 12
Javascript Question

Updating multiple documents with different values

I'm using jquery ui's sortable function (source) to re-arrange elements. I've built custom callbacks to create an list of those elements. So when i move an element, all elements is given a new position id. It could look like this:

[{
id_of_element_in_database: 12,
new_position: 0
}, {
id_of_element_in_database: 16,
new_position: 1
}, {
id_of_element_in_database: 14,
new_position: 2
}]


I'm sending this list to my back-end by doing a simple Ajax post

$.post('/position', { data: list });


Route

router.post('/position', (req, res) => {
console.log(req.body.data); // This prints the array of objects above.
});


Schema

mongoose.Schema({
id: Number,
position: Number,
...
});


Now I can't figure out how to change the position of all documents effectively. Creating a crappy loop of the array and doing multiple database-requests can't be the best approach.

I've tried that here and this feels so wrong.

for (let i in req.body.data) {
collection.update({ id: req.body.data[i].id }, { position: req.body.data[i].position });


There must be something else i can do to achieve this. I've tried google without any luck.

Answer

You could try the bulkWrite API to carry out the updates in a better way without multiple requests to the server:

var callback = function(err, r){
    console.log(r.matchedCount);
    console.log(r.modifiedCount);
}
// Initialise the bulk operations array
var ops = req.body.data.map(function (item) { 
    return { 
        "updateOne": { 
            "filter": { 
                "id": parseInt(item.id),
                "position": { "$ne": parseInt(item.position) }
            },              
            "update": { "$set": { "position": parseInt(item.position) } } 
        }         
    }    
});

// Get the underlying collection via the native node.js driver collection object
Model.collection.bulkWrite(ops, callback);