将mongo查询的输出重定向到csv文件


85

我将MongoDB 2.2.2用于32位Windows7计算机。我在.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格式。但是我认为只有map-reduce查询支持输出集合。那正确吗?我需要它来进行聚合查询。

谢谢你的帮助 :)


1
如果您经常这样做,则可以考虑使用.NET,python编写独立的EXE,或者可以使用NodeJ。每个驱动器都有一个本机驱动程序,可以轻松执行代码并产生所需的输出。
WiredPrairie

我指的是Zachary在stackoverflow.com/questions/4130849 / ...上的答案,并且能够从json转换为csv。但是,作为替代方案,我可以将json输出到集合中,然后执行mongoexport吗?
Aafreen谢赫

我建议您只使用Node和用于NodeJS的MongoDB驱动程序构建一个小型工具,然后执行所需的任何代码。您将很快获得所需的结果,而根本不需要外壳。这将是非常易于维护(和可调试)的。
WiredPrairie

Answers:


175

我知道这个问题很旧,但是我花了一个小时试图将一个复杂的查询导出到csv,我想分享自己的想法。首先,我无法使任何json到csv转换器正常工作(尽管看起来很有希望)。我最终要做的是在mongo脚本中手动编写csv文件。

这是一个简单的版本,但实际上是我所做的:

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我使用的数据库的名称在哪里。


我如何指定User集合所在的数据库?
Nelu 2013年

2
@NeluMalancea签出他们具有此信息的MongoDB文档。您可以通过添加use <database>脚本顶部来指定数据库
GEverding

2
实际上,由于诸如“ use <database>”之类的shell帮助程序不是javascript,因此不允许使用它们。参见docs.mongodb.org/manual/tutorial/…。而是,像下面这样启动脚本:conn = new Mongo(); db = conn.getDB('your_db_name');
史蒂夫·汉森·史密斯

2
@NeluMalancea mongo命令接受数据库URL(以及用户名,密码……)
iwein15年

3
@NeluMalanceatest中的最后一个命令数据库的名称,只需将其替换为您的数据库的名称即可。
佐尔坦

112

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
1

mongoexport的局限性在于您无法操纵字段。mongo id导出为ObjectId(mongidstring)。如果有人想操纵字段的数据(例如ObjectId(mongidstring).toString()),则能够从mongo shell脚本中导出结果会更好。
Raj006

我可以进行汇总操作吗?
Hendy Irawan

此解决方案有效。但是对于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 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输出到文件。不支持从mongos shell输出csv。您将必须自己编写JavaScript或使用许多可用的转换器之一。例如,谷歌“将json转换为csv”。


0

只是在这里权衡一下我一直在使用的一个不错的解决方案。这类似于上面的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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.