2014-10-20 1 views
3

Я бег моего сценария Монго оболочки, как это:MongoDB printjson будет выводить ObjectId на результат, который не может быть использован для JSON.parse

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

Я использую printjson в myscript.js. MongoDB printjson будет выводить ObjectId в my.json, как это:

"_id" : ObjectId("5444a932ca62bbcba14a1082") 

Я читал некоторые исходный код из Монго оболочки. printjson запустит этот код для объекта ObjectId.

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

после Монго версии 2.2, ObjectId("507c7f79bcf86cd7994f6c0e").toString() возвращает следующую строку:

ObjectId("507c7f79bcf86cd7994f6c0e") 

Это не я хочу. Я использую ObjectId("507c7f79bcf86cd7994f6c0e").valueOf().

Это возвращает следующую строку:

507c7f79bcf86cd7994f6c0e 

наконец, добавить одну строку в myscript.js:

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

я решил мою проблему. но мне не нравится изменять исходное поведение toString(). Есть ли лучшие решения?

ответ

2

Согласовано, изменение функций фреймворка, как это опасная идея. Это изменяет поведение ObjectID.toString для всего остального кода, а не только printjson.

Поскольку структура агрегации MongoDB не позволяет использовать произвольный JavaScript, мы не можем просто сделать что-то вроде db.test.aggregate({$project: {_id: '$_id.valueOf()'}}) или предоставить ему пользовательскую функцию преобразования.

Структура построения карт MongoDB может использовать пользовательские функции JavaScript и может быть в состоянии достичь этого, но она довольно сложная, медленная, и ее использование, как правило, обескуражено.

Ваш лучший вариант - включить это преобразование идентификатора как часть вашего скрипта в той или иной форме. Либо просто преобразовать документ перед печатью Времнного по мере необходимости:

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; 
}; 
+0

Если у меня встроенный документ, ваш метод правильный выбор? – lutaoact

1

В зависимости от того, что в вашем сценарии, вы можете быть в состоянии решить вашу проблему с помощью mongoexport вместо mongo. mongoexport Выход JSON использует «строгий режим» extended json, который действителен JSON и может анализироваться другими инструментами JSON, отличными от Mongo.

Чтобы использовать эту технику, вам нужно будет преобразовать ваш запрос из «режима оболочки» в «строгий режим», передать имя базы данных и имя коллекции в качестве аргументов, а также правильно указать для своей оболочки.Например, возьмем этот запрос, как написано для MONGO оболочки:

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

и преобразовать его в выражение эквивалентной оболочки с mongoexport:

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

Этот выход может быть передан в json_pp или jq или другого инструмента который ожидает действительный JSON в качестве входных данных.