使用连接字段的结果更新文档

时间:2015-11-16 20:34:31

标签: mongodb date mongodb-query aggregation-framework

考虑一个包含以下文件的集合

{
        "_id" : "aaaaaaaaaaaa",
        "title" : "Hello, World!",
        "date" : "Thursday, November 12, 2015",
        "time" : "9:30 AM",
        "endtime" : "11:30 AM"
},
{
        "_id" : "bbbbbbbbbbbb",
        "title" : "To B or not to B",
        "date" : "Thursday, November 12, 2015",
        "time" : "10:30 AM",
        "endtime" : "11:00 AM"
},
{
        "_id" : "cccccccccccc",
        "title" : "Family Time",
        "date" : "Thursday, November 12, 2015",
        "time" : "10:30 AM",
        "endtime" : "12:00 PM"
}

在这个简化的输出中,我的事件的开始时间,结束时间和日期都以字符串形式输入。如何使用update()中使用现有数据计算新的正确形成的Date()的字段 - 我可以实际查询的类型数据。

以下工作可以创建一个新的" iso_start"字段

db.events.update({},{$set: {iso_start:Date()}},{multi: true})

我想我可以构建一种像这样的更新选择

db.events.update({},{$set: {iso_start:Date(date + " " + time)}},{multi: true})db.events.update({},{$set: {iso_end:Date(date + " " + time)}},{multi: true})

但我收到错误"日期未定义。"

更新:this.datethis.time使未定义的错误消失,但插入的日期是当前日期时间。我尝试写new Date(),但插入的日期是ISODate(" 0NaN-NaN-NaNTNaN:NaN:NaNZ")

1 个答案:

答案 0 :(得分:1)

您需要使用.aggregate()方法来访问聚合管道。

$project阶段,您需要使用$concat运算符来连接您的字段。

然后,您可以使用汇总结果使用"bulk"操作来更新集合以提高效率

var bulk = db.events.initializeOrderedBulkOp(); 
var count = 0;
db.events.aggregate([
    { "$project": {
        "iso_start": { "$concat": [ "$date", " ", "$time" ] }, 
        "iso_end": { "$concat": [ "$date", " ", "$endtime" ] }    
    }}
]).forEach(function(doc) { 
    bulk.find({'_id': doc._id}).updateOne({
        "$set": {
            "iso_start": new Date(doc.iso_start),
            "iso_end": new Date(doc.iso_end)
        }
    }); 
    count++; 
    if(count % 200 === 0) { 
        // update per 200 operations and re-init
        bulk.execute();     
        bulk = db.events.initializeOrderedBulkOp(); 
    } 
})
// Clean up queues
if(count > 0) bulk.execute();

完成此操作后,您的文档如下所示:

{
        "_id" : "aaaaaaaaaaaa",
        "title" : "Hello, World!",
        "date" : "Thursday, November 12, 2015",
        "time" : "9:30 AM",
        "endtime" : "11:30 AM",
        "iso_start" : ISODate("2015-11-12T06:30:00Z"),
        "iso_end" : ISODate("2015-11-12T08:30:00Z")
}
{
        "_id" : "bbbbbbbbbbbb",
        "title" : "To B or not to B",
        "date" : "Thursday, November 12, 2015",
        "time" : "10:30 AM",
        "endtime" : "11:00 AM",
        "iso_start" : ISODate("2015-11-12T07:30:00Z"),
        "iso_end" : ISODate("2015-11-12T08:00:00Z")
}

这不是故事的结尾,因为"Bulk" API及其相关方法在即将发布的版本(版本3.2)中已弃用,因此从该版本开始,我们需要使用db.collection.bulkWrite()方法。

var operations = [];
db.events.aggregate([
    { "$project": {
        "iso_start": { "$concat": [ "$date", " ", "$time" ] }, 
        "iso_end": { "$concat": [ "$date", " ", "$endtime" ] }    
    }}
]).forEach(function(doc) {
    var operation = {
        updateOne: { 
            filter: { "_id": doc._id }, 
            update: { 
                "$set":  { 
                   "iso_start": new Date(doc.iso_start),
                   "iso_end": new Date(doc.iso_end)
                }
            }
        }
    }; 
    operations.push(operation); 
})
operations.push({ ordered: true, writeConcern: { w: "majority", wtimeout: 5000 } });
db.events.bulkWrite(operations)