我可以从控制台中的日期创建新的ObjectId var吗?

时间:2014-02-24 09:23:26

标签: mongodb

我刚刚将一些数据从SQL数据库导入到MongoDB集合中并进行了一些重构。我刚刚将'yyyy-mm-dd'格式的字符串日期值转换为:

db.Statistic.find({d: {$exists: false}}).forEach(function (x) {
  var d = ISODate(x.date);
  db.Statistic.update(x, {$set: {"d": d}});
});

运作良好。现在我想用_id重建对象,它使用这个日期,这样我就不需要一个单独的日期字段。我试过(和许多变化):

db.Statistic.find({d: {$exists: true}}).forEach(function (x) {
  var oldId = x._id;
  x._id = new ObjectId(x.d);
  db.Statistic.save(x);
  db.Statistic.remove({_id: oldId});
});

但我得到Error: invalid object id: length我假设因为控制台的ObjectId构造函数不接受构建新objectId的日期。有没有办法在控制台中执行此操作?

2 个答案:

答案 0 :(得分:1)

是的,你的逻辑在这里有两个问题。

首先使用ObjectId()函数,您要么将实际ObjectId的字符串化版本指定为参数,要么不指定任何内容。所以你不能把它当作你想要做的日期。

第二个问题是,您不能update(这是save特殊的快捷方式)文档的_id字段。把它想象成一把钥匙。不允许更改它。

虽然您为自己想出了一个不同的策略 _id(不同的问题),但请注意,要进行此类更改,您需要“写出”收藏。

也就是说,在shell中生成ObjectId对构造函数有这个限制。某些驱动程序实现执行提供了在Id生成中使用您自己的日期种子的方法。您仍然受到我提到的相同限制。但这些信息可能有用。以下是两篇引用此帖子的帖子:

Generating Mongo ObjectId (_id) with custom time?

Create MongoDB ObjectID from date in the past using PHP driver

答案 1 :(得分:0)

我成功实现了我的目标。我最后得到了一个小脚本 - 我已经包含调试信息,以防将来对某人有用:

db.Statistic.find().forEach(function (x) {
  var oldId = x._id;
  print("oldId=" + oldId);
  var oldMachineTime = ("" + oldId).substring(8, 24);
  print("oldMachineTime=" + oldMachineTime);
  print("x.d.getTime=" + x.d.getTime());
  var timePart = Math.floor(x.d.getTime() / 1000);
  print("timePart=" + timePart);
  var timePart16 = timePart.toString(16);
  print("timePart16=" + timePart16);
  var newHex = timePart16 + oldMachineTime;
  print("newHex=" + newHex);
  x._id = ObjectId(newHex);
  print("x._id=" + x._id);
  db.Statistic.save(x);
  db.Statistic.remove({_id: oldId});
});

然后我确认了一部分数据:

db.Statistic.find(...).sort({"date": 1}).limit(1000).forEach(function (x) {
  print("id=" + x._id);
  var idDate = new Date(x._id.getTimestamp());
  print("id.date=" + idDate);
  print("date=" + x.date);
});

总之,我现在已经将SQL表中的原始日期集成到这些对象的ObjectId中。我现在可以删除旧的日期字段,并在需要时从_id.getTimestamp()读取它。