Mongo : 如何将所有使用长时间戳的条目转换为 ISODate?
Mongo : How to convert all entries using a long timeStamp to an ISODate?
我有一个当前的 Mongo 数据库,其中包含累积的 entries/fields
{
name: "Fred Flintstone",
age : 34,
timeStamp : NumberLong(14283454353543)
}
{
name: "Wilma Flintstone",
age : 33,
timeStamp : NumberLong(14283454359453)
}
等等...
问题:我想将数据库中的所有条目转换为它们相应的 ISODate - 如何做到这一点?
想要的结果:
{
name: "Fred Flintstone",
age : 34,
timeStamp : ISODate("2015-07-20T14:50:32.389Z")
}
{
name: "Wilma Flintstone",
age : 33,
timeStamp : ISODate("2015-07-20T14:50:32.389Z")
}
我试过的东西
>db.myCollection.find().forEach(function (document) {
document["timestamp"] = new Date(document["timestamp"])
//Not sure how to update this document from here
db.myCollection.update(document) //?
})
使用聚合管道进行更新操作,只需运行以下更新操作:
db.myCollection.updateMany(
{ },
[
{ $set: {
timeStamp: {
$toDate: '$timeStamp'
}
} },
]
])
通过您的初始尝试,您几乎就成功了,您只需调用 save()
method on the modified document to update it since the method uses either the insert
or the update
command. In the above instance, the document contains an _id
fieldand thus the save()
method is equivalent to an update()
操作,并将 upsert 选项设置为 true 并将查询谓词设置为 _id
领域:
db.myCollection.find().snapshot().forEach(function (document) {
document["timestamp"] = new Date(document["timestamp"]);
db.myCollection.save(document)
})
以上类似于您之前尝试过的显式调用 update()
方法:
db.myCollection.find().snapshot().forEach(function (document) {
var date = new Date(document["timestamp"]);
var query = { "_id": document["_id"] }, /* query predicate */
update = { /* update document */
"$set": { "timestamp": date }
},
options = { "upsert": true };
db.myCollection.update(query, update, options);
})
对于相对较大的集合大小,您的数据库性能会很慢,因此建议使用 mongo bulk updates:
MongoDB 版本 >= 2.6 和 < 3.2:
var bulk = db.myCollection.initializeUnorderedBulkOp(),
counter = 0;
db.myCollection.find({"timestamp": {"$not": {"$type": 9 }}}).forEach(function (doc) {
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "timestamp": new Date(doc.timestamp") }
});
counter++;
if (counter % 1000 === 0) {
// Execute per 1000 operations
bulk.execute();
// re-initialize every 1000 update statements
bulk = db.myCollection.initializeUnorderedBulkOp();
}
})
// Clean up remaining operations in queue
if (counter % 1000 !== 0) bulk.execute();
MongoDB 3.2 版及更新版本:
var ops = [],
cursor = db.myCollection.find({"timestamp": {"$not": {"$type": 9 }}});
cursor.forEach(function (doc) {
ops.push({
"updateOne": {
"filter": { "_id": doc._id } ,
"update": { "$set": { "timestamp": new Date(doc.timestamp") } }
}
});
if (ops.length === 1000) {
db.myCollection.bulkWrite(ops);
ops = [];
}
});
if (ops.length > 0) db.myCollection.bulkWrite(ops);
似乎在 mongo 中尝试从 NumberLong 值实例化 Date 对象时发生了一些麻烦的事情。主要是因为 NumberLong 值被转换为错误的表示形式,并且使用了回退到当前日期。
我和 mongo 战斗了 2 天,终于找到了解决方案。关键是将 NumberLong 转换为 Double ...并将双精度值传递给 Date 构造函数。
这是使用灯泡操作并为我工作的解决方案...
(lastIndexedTimestamp是迁移到ISODate的集合字段,存储在lastIndexed字段中,创建一个临时集合,最后改名为原值。)
db.annotation.aggregate( [
{ $project: {
_id: 1,
lastIndexedTimestamp: 1,
lastIndexed: { $add: [new Date(0), {$add: ["$lastIndexedTimestamp", 0]}]}
}
},
{ $out : "annotation_new" }
])
//drop annotation collection
db.annotation.drop();
//rename annotation_new to annotation
db.annotation_new.renameCollection("annotation");
我有一个当前的 Mongo 数据库,其中包含累积的 entries/fields
{
name: "Fred Flintstone",
age : 34,
timeStamp : NumberLong(14283454353543)
}
{
name: "Wilma Flintstone",
age : 33,
timeStamp : NumberLong(14283454359453)
}
等等...
问题:我想将数据库中的所有条目转换为它们相应的 ISODate - 如何做到这一点?
想要的结果:
{
name: "Fred Flintstone",
age : 34,
timeStamp : ISODate("2015-07-20T14:50:32.389Z")
}
{
name: "Wilma Flintstone",
age : 33,
timeStamp : ISODate("2015-07-20T14:50:32.389Z")
}
我试过的东西
>db.myCollection.find().forEach(function (document) {
document["timestamp"] = new Date(document["timestamp"])
//Not sure how to update this document from here
db.myCollection.update(document) //?
})
使用聚合管道进行更新操作,只需运行以下更新操作:
db.myCollection.updateMany(
{ },
[
{ $set: {
timeStamp: {
$toDate: '$timeStamp'
}
} },
]
])
通过您的初始尝试,您几乎就成功了,您只需调用 save()
method on the modified document to update it since the method uses either the insert
or the update
command. In the above instance, the document contains an _id
fieldand thus the save()
method is equivalent to an update()
操作,并将 upsert 选项设置为 true 并将查询谓词设置为 _id
领域:
db.myCollection.find().snapshot().forEach(function (document) {
document["timestamp"] = new Date(document["timestamp"]);
db.myCollection.save(document)
})
以上类似于您之前尝试过的显式调用 update()
方法:
db.myCollection.find().snapshot().forEach(function (document) {
var date = new Date(document["timestamp"]);
var query = { "_id": document["_id"] }, /* query predicate */
update = { /* update document */
"$set": { "timestamp": date }
},
options = { "upsert": true };
db.myCollection.update(query, update, options);
})
对于相对较大的集合大小,您的数据库性能会很慢,因此建议使用 mongo bulk updates:
MongoDB 版本 >= 2.6 和 < 3.2:
var bulk = db.myCollection.initializeUnorderedBulkOp(),
counter = 0;
db.myCollection.find({"timestamp": {"$not": {"$type": 9 }}}).forEach(function (doc) {
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "timestamp": new Date(doc.timestamp") }
});
counter++;
if (counter % 1000 === 0) {
// Execute per 1000 operations
bulk.execute();
// re-initialize every 1000 update statements
bulk = db.myCollection.initializeUnorderedBulkOp();
}
})
// Clean up remaining operations in queue
if (counter % 1000 !== 0) bulk.execute();
MongoDB 3.2 版及更新版本:
var ops = [],
cursor = db.myCollection.find({"timestamp": {"$not": {"$type": 9 }}});
cursor.forEach(function (doc) {
ops.push({
"updateOne": {
"filter": { "_id": doc._id } ,
"update": { "$set": { "timestamp": new Date(doc.timestamp") } }
}
});
if (ops.length === 1000) {
db.myCollection.bulkWrite(ops);
ops = [];
}
});
if (ops.length > 0) db.myCollection.bulkWrite(ops);
似乎在 mongo 中尝试从 NumberLong 值实例化 Date 对象时发生了一些麻烦的事情。主要是因为 NumberLong 值被转换为错误的表示形式,并且使用了回退到当前日期。
我和 mongo 战斗了 2 天,终于找到了解决方案。关键是将 NumberLong 转换为 Double ...并将双精度值传递给 Date 构造函数。
这是使用灯泡操作并为我工作的解决方案...
(lastIndexedTimestamp是迁移到ISODate的集合字段,存储在lastIndexed字段中,创建一个临时集合,最后改名为原值。)
db.annotation.aggregate( [
{ $project: {
_id: 1,
lastIndexedTimestamp: 1,
lastIndexed: { $add: [new Date(0), {$add: ["$lastIndexedTimestamp", 0]}]}
}
},
{ $out : "annotation_new" }
])
//drop annotation collection
db.annotation.drop();
//rename annotation_new to annotation
db.annotation_new.renameCollection("annotation");