Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upsert issue when updating multiple documents using an array of IDs with $in

This query is doing the job fine :

db.collection.update(
    { "_id": oneIdProvided }, 
    { $inc: { "field": 5 } },{ upsert: true }
)

Now I would like to do the same operation multiple time with different IDs, I thought the good way was to use $in and therefore I tried :

db.collection.update(
    { "_id": { $in: oneArrayOfIds} }, 
    { $inc: { "field": 5 } },{ upsert: true }
)

Problem is : if one of the provided ID in the array is not existing in the collection, a new document is created (which is what I want) but will be attributed an automatic ID, not using the ID I provided and was looking for.

One solution I see could be to do first an insert query with my array of ID (those already existing would not be modified) and then doing my update query with upsert: false

Do you see a way of doing that in only one query ?

like image 714
Felwin Avatar asked Oct 30 '22 14:10

Felwin


1 Answers

We can do this by performing multiple write operations using the bulkWrite() method.

function* range(start, end, step) { 
    for (let val=start; val<end; val+=step)
        yield val
}

let oneArrayOfIds; // For example [1, 2, 3, 4]

let bulkOp = oneArrayOfIds.map( id => { 
    return { 
        "updateOne": { 
            "filter": { "_id": id }, 
            "update": { "$set": { "field": 5 } }, 
            "upsert": true 
        }
    };
});

const limit = 1000;
const len = bulkOp.length;

let chunks = [];
if (len > 1000) {
    for (let index of range(0, len, limit)) {
        db.collection.bulkWrite(bulkOp.slice(index, index+limit));
    }
} else {
    db.collection.bulkWrite(bulkOp);
}   
like image 188
styvane Avatar answered Nov 15 '22 08:11

styvane