Перенаправить вывод запроса mongo в файл csv

88

Я использую MongoDB 2.2.2 для 32-разрядной машины Windows7. У меня есть сложный запрос агрегирования в файле .js. Мне нужно выполнить этот файл в оболочке и направить вывод в файл CSV. Я гарантирую, что запрос вернет "плоский" json (без вложенных ключей), поэтому он по своей сути может быть преобразован в аккуратный csv.

Я знаю про load()и eval(). eval()требует, чтобы я вставил весь запрос в оболочку и разрешает только printjson()внутри скрипта, а мне нужен csv. И, второй способ: .. load()Он выводит результат на экран, и снова в формате json.

Есть ли способ, которым Mongo может выполнить это преобразование из json в csv? (Мне нужен файл csv для подготовки диаграмм по данным). Я думаю:

1. Либо у mongo есть встроенная команда для этого, которую я не могу найти прямо сейчас.
2. Монго не может сделать это за меня; В лучшем случае я могу отправить вывод json в файл, который затем мне нужно будет сам преобразовать в csv.
3. Mongo может отправлять выходные данные json во временную коллекцию, содержимое которой может быть легко mongoexportedпреобразовано в формат csv. Но я думаю, что только запросы map-reduce поддерживают выходные коллекции. Это правильно? Мне он нужен для запроса агрегирования.

Спасибо за любую помощь :)

Аафрин Шейх
источник
1
Если это то, что вы делаете часто, вы можете подумать о написании автономного EXE с использованием .NET, python или NodeJs; у каждого есть собственный драйвер, который упростит выполнение вашего кода и выдаст желаемый результат.
WiredPrairie
Я имею в виду ответ Захари на stackoverflow.com/questions/4130849/… и могу конвертировать из json в csv. Но в качестве альтернативы я могу вывести json в коллекцию, а затем выполнить mongoexport?
Aafreen Sheikh
Я бы порекомендовал вам просто создать небольшую оснастку с использованием Node и драйвера MongoDB для NodeJS, а затем вы можете выполнить любой код, который захотите. Вы получите желаемый результат очень быстро, даже без оболочки. Это было бы очень легко поддерживать (и отлаживать).
WiredPrairie

Ответы:

179

Я знаю, что это старый вопрос, но я потратил час, пытаясь экспортировать сложный запрос в csv, и хотел поделиться своими мыслями. Сначала я не мог заставить работать ни один из конвертеров json в csv (хотя этот выглядел многообещающим). В итоге я написал вручную файл csv в моем сценарии mongo.

Это простая версия, но по сути то, что я сделал:

print("name,id,email");
db.User.find().forEach(function(user){
  print(user.name+","+user._id.valueOf()+","+user.email);
});

Это я просто отправил запрос на стандартный вывод

mongo test export.js > out.csv

где testимя используемой мной базы данных.

GEverding
источник
Как мне указать, в какой базе данных находится коллекция User?
Nelu
2
@NeluMalancea ознакомьтесь с документацией MongoDB, в которой есть эта информация. Вы можете указать БД, добавив use <database>в начало скрипта
GEverding
2
На самом деле, поскольку помощники оболочки, такие как «use <database>», не являются javascript, они не разрешены. См. Docs.mongodb.org/manual/tutorial/… . Вместо этого запустите свой сценарий примерно так: conn = new Mongo (); db = conn.getDB ('your_db_name');
Стив Хансен Смайт,
2
@NeluMalancea команда mongo принимает URL-адрес базы данных (и пользователя, пароль,…)
iwein
3
@NeluMalancea testв последней команде является именем базы данных, просто заменить его с именем базы данных.
Zoltán
116

Встроенный экспорт Mongo работает нормально, если вы не хотите манипулировать данными, такими как формат даты, скрытые типы данных и т. Д.

Следующая команда работает как шарм.

    mongoexport -h localhost -d databse -c collection --type=csv 
    --fields erpNum,orderId,time,status 
    -q '{"time":{"$gt":1438275600000}, "status":{"$ne" :"Cancelled"}}' 
    --out report.csv
thisarattr
источник
17
Благодаря тонну! Подсказка: теперь это --type=csvвместо --csv.
янв., В
Ограничение mongoexport заключается в том, что вы не можете манипулировать полями. Идентификатор mongo экспортируется как ObjectId (mongidstring). Возможность экспортировать результаты из сценария оболочки mongo лучше, если кто-то хочет манипулировать данными полей (например, ObjectId (mongidstring) .toString ()).
Raj006 05
1
могу ли я выполнять операции агрегирования?
Hendy
Это решение сработало. Но для Windows мне пришлось внести две поправки: мне просто нужен двойной апостроф снаружи и одиночный апостроф внутри, например -q "{name: 'stackoverflow'}", также для указания порта команда -p не работает, я использовал - -port 27000.
nurb
10

Расширение других ответов:

Я нашел ответ @ GEverding самым гибким. Он также работает с агрегацией:

test_db.js

print("name,email");

db.users.aggregate([
    { $match: {} }
]).forEach(function(user) {
        print(user.name+","+user.email);
    }
});

Выполните следующую команду, чтобы экспортировать результаты:

mongo test_db < ./test_db.js >> ./test_db.csv

К сожалению, он добавляет дополнительный текст в файл CSV, который требует обработки файла, прежде чем мы сможем его использовать:

MongoDB shell version: 3.2.10 
connecting to: test_db

Но мы можем заставить оболочку mongo перестать выплевывать эти комментарии и печатать только то, что мы просили, передав --quietфлаг

mongo --quiet test_db < ./test_db.js >> ./test_db.csv
Лаки Сони
источник
1
Отредактировать его ответ будет лучше, чем добавить новый.
Ренато Бэк
6

Вот что можно попробовать:

print("id,name,startDate")
cursor = db.<collection_name>.find();
while (cursor.hasNext()) {
    jsonObject = cursor.next();
    print(jsonObject._id.valueOf() + "," + jsonObject.name + ",\"" + jsonObject.stateDate.toUTCString() +"\"")

}

Сохраните это в файле, скажем, "export.js". Выполните следующую команду:

mongo <host>/<dbname> -u <username> -p <password> export.js > out.csv
Шириш Кумар
источник
5

Посмотри на это

для вывода из оболочки mongo в файл. Нет поддержки вывода csv из оболочки mongos. Вам придется написать javascript самостоятельно или использовать один из множества доступных конвертеров. Например, Google "конвертирует json в csv".

чудак
источник
1

Просто взвесил здесь хорошее решение, которое я использовал. Это похоже на решение Lucky Soni, приведенное выше, в том, что оно поддерживает агрегирование, но не требует жесткого кодирования имен полей.

cursor = db.<collection_name>.<my_query_with_aggregation>;

headerPrinted = false;
while (cursor.hasNext()) {
    item = cursor.next();
    
    if (!headerPrinted) {
        print(Object.keys(item).join(','));
        headerPrinted = true;
    }

    line = Object
        .keys(item)
        .map(function(prop) {
            return '"' + item[prop] + '"';
        })
        .join(',');
    print(line);
}

Сохраните это как .jsфайл, в этом случае мы назовем его example.jsи запустим с помощью командной строки mongo следующим образом:

mongo <database_name> example.js --quiet > example.csv
ТиммиГи
источник
0

Я использую следующую технику. Это позволяет легко синхронизировать имена столбцов с содержимым:

var cursor = db.getCollection('Employees.Details').find({})

var header = []
var rows = []

var firstRow = true
cursor.forEach((doc) => 
{
    var cells = []
    
    if (firstRow) header.push("employee_number")
    cells.push(doc.EmpNum.valueOf())

    if (firstRow) header.push("name")
    cells.push(doc.FullName.valueOf())    

    if (firstRow) header.push("dob")
    cells.push(doc.DateOfBirth.valueOf())   
    
    row = cells.join(',')
    rows.push(row)    

    firstRow =  false
})

print(header.join(','))
print(rows.join('\n'))
Фидель
источник
0

При выполнении сценария на удаленном сервере. Mongo добавит свой собственный вывод журнала, который мы могли бы исключить из нашего файла. --quietопция отключит только журналы, связанные с подключением. Не все журналы монго. В таком случае нам может потребоваться вручную отфильтровать ненужные строки. Пример для Windows:

mongo dbname --username userName --password password --host replicaset/ip:port --quiet printDataToCsv.js | findstr /v "NETWORK" > data.csv

Это передаст вывод сценария по конвейеру и будет использовать его findstrдля фильтрации любых строк, в которых есть строка NETWORK. Дополнительная информация о findstr: https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/findstr

Версия для Linux будет использовать grep.

Саймон Катански
источник