Mongo sorgusunun çıktısını bir csv dosyasına yönlendirme


88

32 bit Windows7 makinesi için MongoDB 2.2.2 kullanıyorum. .Js dosyasında karmaşık bir toplama sorgum var. Bu dosyayı kabukta çalıştırmam ve çıktıyı bir CSV dosyasına yönlendirmem gerekiyor. Sorgunun "düz" bir json (iç içe anahtarlar yok) döndürdüğünden emin olurum, böylece doğal olarak düzgün bir csv'ye dönüştürülebilir.

Bilmem load()ve eval(). eval()tüm sorguyu kabuğa yapıştırmamı gerektiriyor ve printjson()csv'ye ihtiyacım varken yalnızca komut dosyasının içine izin veriyor . Ve ikinci yol: .. load()Çıktıyı ekrana ve tekrar json formatında yazdırır.

Mongo'nun bu dönüşümü json'dan csv'ye yapmasının bir yolu var mı? (Veriler üzerinde grafikler hazırlamak için csv dosyasına ihtiyacım var). Şöyle düşünüyorum:

1. Her iki mongo da bunun için şu anda bulamadığım yerleşik bir komuta sahiptir.
2. Mongo bunu benim için yapamaz; En fazla json çıktısını, daha sonra csv'ye dönüştürmem gereken bir dosyaya gönderebilirim.
3. Mongo, json çıktısını, içeriği kolaylıkla mongoexportedcsv formatında olabilen geçici bir koleksiyona gönderebilir . Ancak, yalnızca harita azaltma sorgularının çıktı koleksiyonlarını desteklediğini düşünüyorum. Bu doğru mu? Bir toplama sorgusu için buna ihtiyacım var.

Herhangi bir yardım için teşekkürler :)


1
Bu sık yaptığınız bir şeyse, .NET, python kullanarak bağımsız bir EXE yazmayı düşünebilir veya NodeJ'leri kullanabilirsiniz; her birinin kodunuzu çalıştırmayı ve istenen çıktıyı üretmeyi kolaylaştıracak yerel bir sürücüsü vardır.
WiredPrairie

Zachary'nin stackoverflow.com/questions/4130849/… adresindeki cevabına atıfta bulunuyorum ve json'dan csv'ye dönüştürme yapabiliyorum. Ancak alternatif olarak, json'u bir koleksiyona çıktısınıp ardından bir mongoexport yapabilir miyim?
Aafreen Sheikh

NodeJS için Node ve MongoDB sürücüsünü kullanarak küçük bir kablo demeti oluşturmanızı ve ardından istediğiniz kodu çalıştırmanızı öneririm. İstediğiniz sonuçları kabuğa hiç ihtiyaç duymadan çok hızlı bir şekilde alırsınız. Çok bakım yapılabilir (ve hata ayıklama yapılabilir) olacaktır.
WiredPrairie

Yanıtlar:


179

Bu sorunun eski olduğunu biliyorum ama karmaşık bir sorguyu csv'ye aktarmaya çalışırken bir saatimi harcıyorum ve düşüncelerimi paylaşmak istedim. İlk önce json'dan csv'ye dönüştürücülerin çalışmasını sağlayamadım ( bu umut verici görünmesine rağmen ). Yaptığım şey, csv dosyasını mongo betiğimde elle yazmaktı.

Bu basit bir versiyon ama aslında yaptığım şey:

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

Bu sadece sorguyu stdout'a gönderdim

mongo test export.js > out.csv

testkullandığım veritabanının adı nerede .


Kullanıcı koleksiyonunun hangi veritabanında olduğunu nasıl belirtebilirim?
Nelu

2
@NeluMalancea , bu bilgilere sahip oldukları MongoDB belgelerine bakın . use <database>
DB'yi

2
Aslında, "<database> kullan" gibi kabuk yardımcıları javascript olmadığından, bunlara izin verilmez. Docs.mongodb.org/manual/tutorial/… bakın . Bunun yerine, betiğinize şu şekilde başlayın: conn = new Mongo (); db = conn.getDB ('your_db_name');
Steve Hansen Smythe

2
Mongo komutu bir db url kabul @NeluMalancea (ve kullanıcı, pas, ...)
Iwein

3
@NeluMalancea testson komuta olduğu veritabanının adı, sadece veritabanınızın adını koyar.
Zoltán

116

Tarih formatlama, gizli veri türleri vb. Gibi herhangi bir veri manipülasyonu istemediğiniz sürece Mongo'nun dahili dışa aktarımı iyi çalışıyor

Aşağıdaki komut cazibe olarak çalışır.

    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
Çok teşekkürler! İpucu: şimdi --type=csvyerine --csv.
Ocak

Mongoexport'un sınırlaması, alanları değiştirememenizdir. Mongo kimliği, ObjectId (mongidstring) olarak dışa aktarılır. Birisi alanların verilerini değiştirmek istiyorsa sonuçları bir mongo kabuk betiğinden dışa aktarabilmek daha iyidir (örneğin, ObjectId (mongidstring) .toString ()).
Raj006

1
toplama işlemleri yapabilir miyim?
Hendy Irawan

Bu çözüm işe yaradı. Ancak Windows için iki değişiklik yapmak zorunda kaldım: Dışarıdan çift kesme işaretine ve içeride bu gibi tek kesme işaretine ihtiyacım vardı -q "{name: 'stackoverflow'}", ayrıca -p komutunu belirten bağlantı noktası için de çalışmadı, kullandım - -port 27000.
nurb

10

Diğer cevapları genişletme:

@ GEverding'in yanıtını en esnek buldum. Aynı zamanda toplama ile de çalışır:

test_db.js

print("name,email");

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

Sonuçları dışa aktarmak için aşağıdaki komutu yürütün:

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

Maalesef, CSV dosyasına, biz onu kullanmadan önce işlenmesini gerektiren ek metin ekler:

MongoDB shell version: 3.2.10 
connecting to: test_db

Ancak, mongo kabuğunun bu yorumları yaymasını durdurabiliriz ve yalnızca --quietbayrağı uzatarak istediğimizi yazdırabiliriz.

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

1
Cevabını düzenlemek, yenisini eklemekten daha iyi olacaktır.
Renato Geri

6

İşte deneyebileceğiniz şeyler:

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

}

Bunu bir dosyaya kaydedin, "export.js" deyin. Aşağıdaki komutu çalıştırın:

mongo <host>/<dbname> -u <username> -p <password> export.js > out.csv

5

Göz at bu

mongo kabuğundan dosyaya çıktı almak için. Mongos kabuğundan csv çıkışı desteği yoktur. Javascript'i kendiniz yazmanız veya mevcut birçok dönüştürücüden birini kullanmanız gerekir. Örneğin Google "json’ı csv’ye dönüştür".


1

Sadece burada kullandığım güzel bir çözümle tartıyorum. Bu, toplamayı desteklemesi açısından Lucky Soni'nin yukarıdaki çözümüne benzer , ancak alan adlarının sabit kodlanmasını gerektirmez.

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);
}

Bunu bir .jsdosya olarak kaydedin , bu durumda onu arayacağız example.jsve aşağıdaki gibi mongo komut satırı ile çalıştıracağız:

mongo <database_name> example.js --quiet > example.csv

0

Aşağıdaki tekniği kullanıyorum. Sütun adlarının içerikle senkronize olmasını kolaylaştırır:

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

Uzak bir sunucuda bir komut dosyası çalıştırırken. Mongo, dosyamızdan çıkarmak isteyebileceğimiz kendi günlük çıktısını ekleyecektir. --quietseçeneği yalnızca bağlantı ile ilgili günlükleri devre dışı bırakır. Tüm mongo günlükleri değil. Böyle bir durumda gereksiz hatları manuel olarak filtrelememiz gerekebilir. Windows tabanlı bir örnek:

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

Bu, komut dosyası çıktısını yönlendirir ve findstriçinde NETWORK dizesi bulunan tüm satırları filtrelemek için kullanır . Findstr hakkında daha fazla bilgi: https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/findstr

Bunun bir Linux sürümü kullanacaktır grep.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.