Mongodb printjson will print ObjectId for result which cannot be used for JSON.parse

I run my mongo shell script like this:

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

      

I am using printjson

in myscript.js. mongodb printjson will output the ObjectId in my.json

, for example:

"_id" : ObjectId("5444a932ca62bbcba14a1082")

      

I have read some source code from mongo shell. printjson

will run this code on the ObjectId object.

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

      

after mongo 2.2, ObjectId("507c7f79bcf86cd7994f6c0e").toString()

will return the following line:

ObjectId("507c7f79bcf86cd7994f6c0e")

      

I do not want. I am using ObjectId("507c7f79bcf86cd7994f6c0e").valueOf()

.

This will return the following line:

507c7f79bcf86cd7994f6c0e

      

Finally, I'll add one line to myscript.js

:

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

      

I solved my problem. but I don't like changing the original behavior toString()

. Are there any better solutions?

+3


source to share


2 answers


Agreed, changing framework functions like this is a dangerous idea. This changes the behavior ObjectID.toString

for all other code, not just printjson

.

Since MongoDB's aggregation framework does not allow arbitrary JavaScript, we cannot just do something like db.test.aggregate({$project: {_id: '$_id.valueOf()'}})

or use a custom transform function for it.

MongoDB's map pruning framework may use JavaScript UDFs and may be able to achieve this, but it is quite complex, slow, and generally discouraged to use.

Your best option is to include this ID conversion as part of your script in one form or another. Or just convert the document before ad-hoc printing if needed:



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

      

Either make it more complex and complete it in your own print function, or replace or decorate the original function printjson

, for example. modify the print-only document and undo the change:

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

      

+2


source


Depending on what's in your script, you might be able to solve your problem by using mongoexport

instead mongo

. mongoexport

JSON output uses "strict mode" extended json , which is valid JSON and can be parsed by other non-mongo JSON tools.

To use this method, you will need to convert your query from "shell mode" to "strict mode", pass the database name and collection name as arguments, and specify the correct one for your shell. For example, take this query as written for the mongo shell:

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

      



and convert it to the equivalent shell expression using mongoexport:

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

      

This pin can be connected to json_pp

either jq

or another tool that expects JSON input as input.

+1


source







All Articles