Update multiple docs in a collection using switch case

落花浮王杯 提交于 2019-12-11 05:17:29

问题


I use MongoDB native driver in my NodeJS application.

I have a shifts collection in my database that I need to update. Sample docs in my shifts collection

{
    "_id" : ObjectId("588425105560bd2ba0065fa4"),
    "from" : ISODate("2017-01-23T03:20:00.000Z"),
    "to" : ISODate("2017-01-23T06:20:00.000Z"),
    "jobId" : ObjectId("586efda790541421b0432897"),
    "hourlyRate" : 15
}

{
    "_id" : ObjectId("588425105560bd2ba0065fa5"),
    "from" : ISODate("2017-01-25T03:20:00.000Z"),
    "to" : ISODate("2017-01-25T06:20:00.000Z"),
    "jobId" : ObjectId("586efda790541421b0432897"),
    "hourlyRate" : 15
}

What I need to do is the following -

Update the hourlyRate of all docs that meet the conditions:

  • match the jobId (that is easy)
  • set hourlyRate = 20 if from is a Weekday
  • set hourlyRate = 25 if from is a Saturday
  • set hourlyRate = 30 if from is a Sunday

I would want to do it in a single query as far as possible.

My solution so far:

Use switch case and determine the type of day using $dayOfWeek from Date aggregation function. However, I am not able to combine switch with updateMany.

Any help would be appreciated.


回答1:


You could run the following aggregation pipeline with special operators at your disposal like $switch which is new in MongoDB Server 3.4 and above:

MongoDB Server 3.4:

db.collection('shifts').aggregate([
    {
        "$match": {
            "jobId": ObjectId(job._id),
            "from": { "$gte": new Date() }
        }
    },
    {
        "$project": {
            "hourlyRate": {
                "$switch": {
                    "branches": [
                        {
                            "case": { 
                                "$not": { 
                                    "$in": [
                                        { "$dayOfWeek": "$from" }, 
                                        [1, 7] 
                                    ] 
                                } 
                            }, 
                            "then": 20 
                        },
                        { 
                            "case": { 
                                "$eq": [
                                    { "$dayOfWeek": "$from" }, 
                                    7
                                ] 
                            }, 
                            "then": 25 
                        },
                        { 
                            "case": { 
                                "$eq": [
                                    { "$dayOfWeek": "$from" }, 
                                    1 
                                ] 
                            }, 
                            "then": 30 
                        }
                    ]
                }   
            }               
        }
    }       
], function(err, docs) {
    var ops = [],
        counter = 0;

    docs.forEach(function(doc) {
        ops.push({
            "updateOne": {
                "filter": { "_id": doc._id },
                "update": { "$set": { "hourlyRate": doc.hourlyRate } }
            }
        });
        counter++;

        if (counter % 500 === 0) {
            db.collection('shifts').bulkWrite(ops, function(err, r) {
                // do something with result
            });
            ops = [];
        }
    })

    if (counter % 500 !== 0) {
        db.collection('shifts').bulkWrite(ops, function(err, r) {
            // do something with result
        }
    }       
});

MongoDB Server 3.2

 db.collection('shifts').aggregate([
    {
        "$match": {
            "jobId": ObjectId(job._id),
            "from": { "$gte": new Date() }
        }
    },
    {
        "$project": {
            "hourlyRate": {
                "$cond": [
                    {
                        "$not": { 
                            "$setIsSubset": [
                                [{ "$dayOfWeek": "$from" }], 
                                [1, 7] 
                            ] 
                        } 
                    }, 20,                                
                    { 
                        "$cond": [
                            { "$eq": [
                                { "$dayOfWeek": "$from" }, 
                                7
                            ] },
                            25,
                            { 
                                "$cond": [ 
                                    { "$eq": [
                                        { "$dayOfWeek": "$from" }, 
                                        1 
                                    ] },
                                    30,
                                    "$hourlyRate"
                                ]
                            }
                        ]
                    }                   
                ]                   
            }               
        }
    }
], function(err, docs) {
    var ops = [],
        counter = 0;

    docs.forEach(function(doc) {
        ops.push({
            "updateOne": {
                "filter": { "_id": doc._id },
                "update": { "$set": { "hourlyRate": doc.hourlyRate } }
            }
        });
        counter++;

        if (counter % 500 === 0) {
            db.collection('shifts').bulkWrite(ops, function(err, r) {
                // do something with result
            });
            ops = [];
        }
    })

    if (counter % 500 !== 0) {
        db.collection('shifts').bulkWrite(ops, function(err, r) {
            // do something with result
        }
    }       
})


来源:https://stackoverflow.com/questions/41787787/update-multiple-docs-in-a-collection-using-switch-case

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!