【问题标题】:Need to calculate the datetime difference for the datetime field saved in string format in MongoDB需要计算MongoDB中以字符串格式保存的datetime字段的datetime差异
【发布时间】:2020-05-16 04:12:20
【问题描述】:

示例文档:

{
    "_id" : ObjectId("50ed90a55502684f440001ac"),
    "time" : "2020-05-14T14:12:46.058-0400",
    "ServerTimeStamp" : "2020-05-14T14:12:46.058-0400"

}

{
    "_id" : ObjectId("50ed90a55502684f440001ad"),
    "time" : "2020-05-14T15:12:46.058-0400",
    "ServerTimeStamp" : "2020-05-14T14:12:46.058-0400"
}

{
    "_id" : ObjectId("50ed90a55502684f440001ae"),
    "time" : "2020-05-14T18:12:46.058-0400",
    "ServerTimeStamp" :"2020-05-14T14:12:46.058-0400"
}

我想计算以上行的时间差(以秒为单位)如下,这里时间字段是字符串格式而不是日期。

所需输出:

{

    "_id" : ObjectId("50ed90a55502684f440001ac"),
    "time" : "2020-05-14T14:12:46.058-0400",
    "time_difference" :null
}

{
    "_id" : ObjectId("50ed90a55502684f440001ad"),
    "time" : "2020-05-14T15:12:46.058-0400",
    "time_difference" : 3600  
}

{
    "_id" : ObjectId("50ed90a55502684f440001ae"),
    "time" : "2020-05-14T18:12:46.058-0400",
    "time_difference" : 10800
}

我尝试了以下查询,但出现错误,并且我已经将时间从字符串转换为日期:

db.hello.aggregate(
    {$sort: {$dateFromString:{time: 1}}},
    {$group: {_id: 0, document: {$push: '$$ROOT'}}},
    {$project: {documentAndPrevTime: {$zip: {inputs: ['$document', {$concatArrays: [[null], '$document.time']}]}}}},
    {$unwind: {path: '$documentAndPrevTime'}},
    {$replaceWith: {$mergeObjects: [{$arrayElemAt: ['$documentAndPrevTime', 0]}, {prevTime: {$arrayElemAt: ['$documentAndPrevTime', 1]}}]}},
    {$set: {time_difference: {$trunc: [{$divide: [{$subtract: ['$time', '$prevTime']}, 1000]}]}}},
    {$unset: 'prevTime'}
);

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    您已经编写了所有阶段,但这里的问题是彼此之间没有关系,这意味着在先前设置中所做的更改不会反映在后续步骤中。几个问题:

    {$sort: {$dateFromString:{time: 1}}} // You can't use `$dateFromString` in sort stage. Also syntax of `$dateFromString` is incorrect.
    

    让我们假设它是否有效(它不会但假设)您实际上并没有转换time 并将转换后的时间存储到一个变量以供以后在$group 或更进一步的阶段使用。因此,您需要使用$addFields$project 将其存储到相应文档中的变量中。我没有走得更远,但您可以尝试以下查询:

    查询:

    db.collection.aggregate([
        /** sort on `time` field */
        { $sort: { time: 1 } },
        /** Convert string format of `time` field to milliseconds & store to `convertedTime` field for each doc */
        { $addFields: { convertedTime: { $toLong: { $dateFromString: { dateString: "$time" } } } } },
        /** Group without condition to push all documents into `docs` array */
        {
          $group: { _id: "", docs: { $push: "$$ROOT" } }
        },
        /** re-creating `docs` array */
        {
          $project: {
            _id: 0,
            docs: {
              $reduce: {
                input: { $slice: [ "$docs", 1, { $size: "$docs" } ] }, /** Pick `docs` array without first element for iteration */
                initialValue: {  docObj: [ { $arrayElemAt: [ "$docs", 0 ] } ], previousTime: { $arrayElemAt: [ "$docs.convertedTime", 0 ] } },
                in: {
                  docObj: { $concatArrays: [ "$$value.docObj", [
                        { $mergeObjects: [ "$$this", { time_difference: { $divide: [ { $subtract: [ "$$this.convertedTime", "$$value.previousTime" ] }, 1000 ] } } ] }
                      ]
                    ]
                  },
                  previousTime: "$$this.convertedTime" // Store current doc's time to `previousTime` to utilize for next record
                }
              }
            }
          }
        },
        {
          $unwind: { path: "$docs.docObj" }
        },
        /** Remove additionally added field */
        {
          $project: { "docs.docObj.convertedTime": 0 }
        },
        /** Replace root of the doc with `docs.docObj` */
        {
          $replaceRoot: { newRoot: "$docs.docObj" }
        }
      ])
    

    测试: mongoplayground

    参考:aggregation-pipeline

    注意:此查询不会为第一个文档添加"time_difference" :null,但如果需要,请在initialValue 中尝试此操作:docObj: [ {$mergeObjects :[ { $arrayElemAt: [ "$docs", 0 ] }, { "time_difference" :null } ] ]。另外,我建议将此操作限制为使用$match 作为第一阶段的集合中的某些文档,而不是对所有文档进行此查询原因

    {
       $group: { _id: "", docs: { $push: "$$ROOT" } }
    }
    

    当它在具有庞大数据集的整个集合上完成时,它本身将是一件大事。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-01
      • 1970-01-01
      • 2018-07-04
      • 2015-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多