MongoDB 中的聚合查询使用 javascript 尝试将 UTC 字符串日期转换为 Date 对象

Aggregate query in MongoDB using javascript trying to convert UTC string date to Date object

我正在尝试按小时对日期时间进行分组,并且我正在从 json 文件上传数据。虽然日期时间是 UTC 格式的字符串。如何在流星中使用 javascript 将它们转换为 Date 对象?

var data = Subjects.aggregate([{$match: no_null},
                  { $project: 
                    { bin: { $hour: new Date("$metrics."+metric") } 
                  } },
                  {$group: { _id: "$bin", count: {$sum: 1} } } ])

指标已经采用 UTC 格式。

这是一份文件。

{
    "metrics": {
      "ACT_04": 3.733333333, 
      "ACT_05": 14.5, 
      "ACT_02": "1970-01-01T05:02:30Z", 
      "ACT_03": 7.0833333329999997, 
      "ACT_01": "1970-01-01T20:03:00Z"
    }, 
    "subject_id": "M10965219", 
    "name": "sub-M10965219_Act"
  }

如果 "string" 是 "lexical" ISO 格式,如 "2018-05-15T20:59:31.502Z",那么您 "could" 得到 $substr 部分:

Subjects.aggregate([
  { "$group": {
    "_id": { "$substr": ["$metrics."+metric,0,10] },
    "count": { "$sum": 1 }
  }}
])

如果你有 MongoDB 3.6 可用,那么你 "could" 使用 $dateFromString 将其实际转换为 BSON 日期格式,但你可能希望类似地 t运行对于您实际想要的任何日期舍入,以类似的方式对该字符串进行分类:

Subjects.aggregate([
  { "$group": {
    "_id": {
      "$dateFromString": {
        "dateString": { "$substr": ["$metrics."+metric,0,10] }
      }            
    },
    "count": { "$sum": 1 }
  }}
])

MongoDB 4.0 有 $toDate 更短一点,并进行相同的 BSON 日期转换:

Subjects.aggregate([
  { "$group": {
    "_id": {
      "$toDate": { "$substr": ["$metrics."+metric,0,10] }
    },
    "count": { "$sum": 1 }
  }}
])

但基本事实是,如果您的 "string" 实际上看起来不像那样,并且不能通过支持的运算符以一致的方式真正分解成字符串的各个部分,那么您通常最好将存储在您的集合中的日期首先是实际的 BSON 日期。

这里 "recommended" 要做的实际上是 运行 数据的转换。 mongo shell 应该足以 运行 "one-off" 转换:

var batch = [];

db.subjects.find().forEach(doc => {

  var fields = Object.keys(doc.metrics).map(k => ({
    ['metrics.'+k]: new Date(doc.metrics[k]),
  })).reduce((acc,curr) => Object.assign(acc,curr),{});

  batch.push({
    "updateOne": {
      "filter": doc._id",
      "update": { "$set": fields }
    }
  });

  if ( batch.length > 1000 ) {
     db.subjects.bulkWrite(batch);
     batch = []
  }
})

if ( batch.length > 0 ) {
  db.subjects.bulkWrite(batch);
  batch = [];
}

这是基本过程。当然,如果您的 "strings" 不是 ISO 格式或任何适合传递给 Date() 进行转换的格式,那么您实际上需要采取其他措施。

至少 BSON 日期是一个 8 字节的数据结构,具有 "internal" 数字表示,而等效的 "string" 它至少有 24 字节,甚至更长的单词命名日期和月份。在使用数据库时,以这种形式保留本质上 "numeric" 本质上的数据是有意义的。

我的建议是转换数据,并且可能在导入时转换,或者如果您不能转换,那么至少加载一次到集合中。最好尝试使用字符串来完成它们实际上不应该做的事情。

Note $substr is considered deprecated and actually now aliases $substrBytes, or you can use $substrCP depending on the actual encoding of the data. Older MongoDB releases before 3.2 have the $substr expression only.