เปลี่ยนทิศทางผลลัพธ์ของแบบสอบถาม mongo ไปยังไฟล์ csv


88

ฉันใช้ MongoDB 2.2.2 สำหรับเครื่อง Windows7 แบบ 32 บิต ฉันมีแบบสอบถามการรวมที่ซับซ้อนในไฟล์. js ฉันต้องการเรียกใช้ไฟล์นี้บนเชลล์และกำหนดผลลัพธ์ไปยังไฟล์ CSV ฉันแน่ใจว่าข้อความค้นหาส่งคืน json "แบน" (ไม่มีคีย์ซ้อนกัน) ดังนั้นจึงสามารถแปลงเป็น csv ที่เรียบร้อยได้โดยเนื้อแท้

ฉันรู้เกี่ยวกับload()และeval(). eval()ต้องการให้ฉันวางแบบสอบถามทั้งหมดลงในเชลล์และอนุญาตเฉพาะprintjson()ภายในสคริปต์ในขณะที่ฉันต้องการ csv และวิธีที่สอง: load().. มันพิมพ์ผลลัพธ์บนหน้าจอและอีกครั้งในรูปแบบ json

มีวิธีที่ Mongo สามารถแปลงจาก json เป็น csv ได้หรือไม่? (ฉันต้องการไฟล์ csv เพื่อเตรียมแผนภูมิเกี่ยวกับข้อมูล) ฉันคิดว่า:

1. mongo มีคำสั่งในตัวสำหรับสิ่งนี้ซึ่งฉันไม่สามารถหาได้ในตอนนี้
2. Mongo ไม่สามารถทำเพื่อฉันได้ ฉันสามารถส่งเอาต์พุต json ไปยังไฟล์ได้มากที่สุดซึ่งฉันต้องแปลงเป็น csv ด้วยตัวเอง
3. Mongo สามารถส่งเอาต์พุต json ไปยังคอลเลกชันชั่วคราวซึ่งเนื้อหาสามารถเป็นmongoexportedรูปแบบ csv ได้อย่างง่ายดาย แต่ฉันคิดว่ามีเพียงการค้นหาการลดแผนที่เท่านั้นที่รองรับคอลเล็กชันเอาต์พุต นั่นถูกต้องใช่ไหม? ฉันต้องการมันสำหรับแบบสอบถามการรวม

ขอบคุณสำหรับความช่วยเหลือ :)


1
หากเป็นสิ่งที่คุณทำบ่อยๆคุณอาจลองเขียน EXE แบบสแตนด์อโลนโดยใช้. NET, python หรือคุณอาจใช้ NodeJs แต่ละตัวมีไดรเวอร์ดั้งเดิมที่จะทำให้ง่ายต่อการรันโค้ดของคุณและสร้างผลลัพธ์ที่ต้องการ
WiredPrairie

ฉันอ้างถึงคำตอบของ Zachary ใน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);
});

นี่ฉันแค่ส่งคำถามไปที่ stdout

mongo test export.js > out.csv

ที่testเป็นชื่อของการใช้งานที่ฉันฐานข้อมูล


ฉันจะระบุได้อย่างไรว่าคอลเลกชันผู้ใช้อยู่ในฐานข้อมูลใด
Nelu

2
@NeluMalancea ตรวจสอบเอกสาร MongoDB ที่พวกเขามีข้อมูลนี้ คุณสามารถระบุฐานข้อมูลได้โดยเพิ่มuse <database>ที่ด้านบนสุดของสคริปต์
GEverding

2
อันที่จริงเนื่องจากตัวช่วยเชลล์เช่น "ใช้ <database>" ไม่ใช่ JavaScript จึงไม่ได้รับอนุญาต ดูdocs.mongodb.org/manual/tutorial/... ให้เริ่มสคริปต์ของคุณในลักษณะนี้แทน: conn = new Mongo (); db = conn.getDB ('your_db_name');
Steve Hansen Smythe

2
@NeluMalancea คำสั่ง mongo ยอมรับ db url (และ user, pass, ... )
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

17
ขอบคุณมาก! คำแนะนำ: ตอนนี้มันเป็นแทน--type=csv --csv
ม.ค.

ข้อ จำกัด ของ mongoexport คือคุณไม่สามารถจัดการกับช่องได้ mongo id ส่งออกเป็น ObjectId (mongidstring) ความสามารถในการเอ็กซ์พอร์ตผลลัพธ์จาก mongo เชลล์สคริปต์จะดีกว่าถ้ามีคนต้องการจัดการข้อมูลของฟิลด์ (เช่น ObjectId (mongidstring) .toString ())
Raj006

1
ฉันสามารถดำเนินการรวมได้หรือไม่?
Hendy Irawan

วิธีนี้ใช้ได้ผล แต่สำหรับ Windows ฉันต้องทำการแก้ไขสองครั้ง: ฉันต้องการแค่เครื่องหมายวรรคตอนคู่จากภายนอกและเครื่องหมายอะพอสทรอฟีเดี่ยวภายในเช่นนี้ -q "{name: 'stackoverflow'}" สำหรับพอร์ตที่ระบุคำสั่ง -p ไม่ทำงานฉันใช้ - - พอร์ต 27000
นูร์บ

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 shell หยุดการแสดงความคิดเห็นเหล่านั้นและพิมพ์เฉพาะสิ่งที่เราขอโดยส่ง--quietแฟล็ก

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

1
การแก้ไขคำตอบของเขาจะดีกว่าการเพิ่มคำตอบใหม่
Renato ย้อนกลับ

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 shell ไปยังไฟล์ ไม่มีการสนับสนุนสำหรับเอาต์พุต csv จาก mongos shell คุณจะต้องเขียนจาวาสคริปต์ด้วยตัวเองหรือใช้หนึ่งในตัวแปลงที่มีอยู่ 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ตัวเลือกจะปิดใช้งานบันทึกที่เกี่ยวข้องกับการเชื่อมต่อเท่านั้น ไม่ใช่บันทึกทั้งหมดของ Mongo ในกรณีนี้เราอาจต้องกรองบรรทัดที่ไม่จำเป็นออกด้วยตนเอง ตัวอย่างที่ใช้ 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

grepรุ่นลินุกซ์นี้จะใช้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.