node.js - 使用 switch case 更新集合中的多个文档

标签 node.js mongodb switch-statement mongodb-query aggregation-framework

我在 NodeJS 应用程序中使用 MongoDB native 驱动程序。

我的数据库中有一个需要更新的 shifts 集合。我的轮类集合中的示例文档

{
    "_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
}

我需要做的是以下 -

更新满足条件的所有文档的hourlyRate:

  • 匹配 jobId(很简单)
  • 如果 from 是工作日,则设置 hourlyRate = 20
  • 如果 from 是星期六,则设置 hourlyRate = 25
  • 如果 from 是星期日,则设置 hourlyRate = 30

我希望尽可能在单个查询中完成此操作。

到目前为止我的解决方案:

使用 switch case 并使用日期聚合函数中的 $dayOfWeek 确定日期类型。但是,我无法将 switch 与 updateMany 结合起来。

如有任何帮助,我们将不胜感激。

最佳答案

您可以使用您可以使用的特殊运算符来运行以下聚合管道,例如 $switch 这是 MongoDB Server 3.4 及更高版本中的新增功能:

MongoDB 服务器 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 服务器 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
        }
    }       
})

关于node.js - 使用 switch case 更新集合中的多个文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41787787/

相关文章:

javascript - 为什么 Node.js 的 Assert.js 在他们的代码中使用 !!!value?它有什么作用?

python - Pymongo 查询与字典内的字典?

Javascript 将 switch 的大小写绑定(bind)到 html 按钮

c - 双链表-C

node.js - 使用异步/等待的 mongodb 连接 - NodeJS

c++ LNK2019错误,未解析的外部字符

node.js - 在 Node.js 应用程序中使用 SSL 时遇到问题

node.js - API 4.0 现已弃用位置快速回复。请参阅我们的开发者文档以获取更多信息

node.js - 异步函数完成后如何发送json

mongodb - 在mongodb中调用ensureindex的优势仅仅是速度吗?