mongodb printjson将ObjectId输出到结果,不能用于JSON.parse

时间:2014-10-20 06:24:04

标签: json mongodb tostring mongo-shell

我像这样运行我的mongo shell脚本:

mongo --quiet myscript.js > /tmp/my.json

我在myscript.js中使用printjson。 mongodb printjson会将ObjectId输出到my.json,如下所示:

"_id" : ObjectId("5444a932ca62bbcba14a1082")

我从mongo shell中读到了一些源代码。 printjson将为ObjectId对象运行此代码。

> x._id.tojson
function (){
    return this.toString();
}

在mongo 2.2版之后,ObjectId("507c7f79bcf86cd7994f6c0e").toString()将返回以下字符串:

ObjectId("507c7f79bcf86cd7994f6c0e")

这不是我想要的。我使用ObjectId("507c7f79bcf86cd7994f6c0e").valueOf()

这将返回以下字符串:

507c7f79bcf86cd7994f6c0e

最后,我在myscript.js中添加了一行:

ObjectId.prototype.toString = function() { return '"' + this.valueOf() + '"'; }

我解决了我的问题。但我不喜欢改变toString()的原始行为。 有没有更好的解决方案?

2 个答案:

答案 0 :(得分:2)

同意,修改这样的框架功能是一个危险的想法。这也改变了所有其他代码的ObjectID.toString行为,而不只是printjson

由于MongoDB聚合框架不允许使用任意JavaScript,因此我们不能只执行db.test.aggregate({$project: {_id: '$_id.valueOf()'}})之类的操作或为其提供自定义转换函数。

MongoDB map-reduce框架可以使用自定义JavaScript函数并且可以实现这一点,但它相当精细,缓慢,并且通常不鼓励使用它。

您最好的选择是以某种形式将此ID转换作为脚本的一部分。在根据需要进行ad-hoc打印之前,只需转换文档:

var cursor = db.test.find();
while (cursor.hasNext()) {
    var doc = cursor.next();
    doc._id = doc._id.valueOf();
    printjson(doc);
}

或者更复杂并将其包装在您自己的打印功能中,或者替换或修饰原始的printjson功能,例如:修改文档只是为了打印并回滚更改:

var theirPrintjson = printjson;
var printjson = function(doc) {
    var id = doc._id;
    doc._id = doc._id.valueOf();
    theirPrintjson(doc);
    doc._id = id;
};

答案 1 :(得分:2)

根据脚本中的内容,您可以使用mongoexport代替mongo来解决问题。 mongoexport JSON输出使用extended json的“严格模式”,它是有效的JSON,可以由其他非mongo JSON工具解析。

要使用此技术,您需要将查询从“shell模式”转换为“严格模式”,将数据库名称和集合名称作为参数传递,并为shell正确引用。例如,将此查询视为为mongo shell编写的:

db.myItemsCollection.find({creationDate: {$gte: ISODate("2016-09-29")}})

并使用mongoexport将其转换为等效的shell表达式:

mongoexport --jsonArray -d myDbName -c myItemsCollection -q '{"creationDate": {"$gte": {"$date": "2016-09-29T00:00Z"}}}'

此输出可以通过管道传输到json_ppjq或其他需要有效JSON作为输入的工具。