我像这样运行我的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()
的原始行为。
有没有更好的解决方案?
答案 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_pp
或jq
或其他需要有效JSON作为输入的工具。