我刚刚将一些数据从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的日期。有没有办法在控制台中执行此操作?
答案 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()
读取它。