【问题标题】:Redirect output of mongo query to a csv file将 mongo 查询的输出重定向到 csv 文件
【发布时间】:2013-01-06 20:22:38
【问题描述】:

我在 32 位 Windows7 机器上使用 MongoDB 2.2.2。我在 .js 文件中有一个复杂的聚合查询。我需要在 shell 上执行这个文件并将输出定向到 CSV 文件。我确保查询返回“平面”json(没有嵌套键),因此它本质上可以转换为整洁的 csv。

我知道load()eval()eval() 要求我将整个查询粘贴到 shell 中,并且只允许在脚本中使用 printjson(),而我需要 csv。并且,第二种方式:load()..它在屏幕上打印输出,然后以 json 格式再次打印。

Mongo 有没有办法从 json 到 csv 进行这种转换? (我需要 csv 文件来准备数据图表)。我在想:

1. mongo 都有一个我现在找不到的内置命令。
2. Mongo不能帮我做;我最多可以将 json 输出发送到一个文件,然后我需要自己将其转换为 csv。
3. Mongo可以将json输出发送到一个临时集合,其中的内容可以很容易的将mongoexported转成csv格式。但我认为只有 map-reduce 查询支持输出集合。那正确吗?我需要它来进行聚合查询。

感谢您的帮助:)

【问题讨论】:

  • 如果这是你经常做的事情,你可以考虑使用 .NET、python 编写一个独立的 EXE,或者你可以使用 NodeJs;每个都有一个本机驱动程序,可以轻松执行您的代码并产生所需的输出。
  • 我指的是 Zachary 在stackoverflow.com/questions/4130849/… 上的回答,并且能够从 json 转换为 csv。但作为替代方案,我可以将 json 输出到集合然后执行 mongoexport 吗?
  • 我建议您使用 Node 和 NodeJS 的 MongoDB 驱动程序构建一个小工具,然后您可以执行任何您想要的代码。你会很快得到你想要的结果,而不需要 shell。这将是非常可维护(和可调试)的。

标签: mongodb mongodb-.net-driver mongodb-query


【解决方案1】:

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

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

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

【讨论】:

  • 如何指定用户集合所在的数据库?
  • @NeluMalancea 查看 MongoDB docs 他们有这些信息。您可以通过在脚本顶部添加use <database> 来指定数据库
  • 实际上,由于诸如“use ”之类的shell助手不是javascript,所以它们是不允许的。见docs.mongodb.org/manual/tutorial/…。相反,启动你的脚本是这样的: conn = new Mongo(); db = conn.getDB('your_db_name');
  • @NeluMalancea mongo 命令接受一个 db url(和用户,通过,...)
  • @NeluMalancea test 在最后一个命令中数据库的名字,用你的数据库名字替换就好了。
【解决方案2】:

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

【讨论】:

  • 非常感谢!提示:现在是--type=csv 而不是--csv
  • mongoexport 的限制是不能操作字段。 mongo id 导出为 ObjectId(mongodstring)。如果有人想要操作字段的数据(例如 ObjectId(mongidstring).toString()),那么能够从 mongo shell 脚本中导出结果会更好。
  • 可以做聚合操作吗?
  • 此解决方案有效。但是对于 Windows,我必须进行两项修改:我只需要来自外部的双撇号和内部的单撇号,例如 -q "{name:'stackoverflow'}" ,对于端口指定 -p 命令也不起作用,我使用了 - -端口 27000。
  • 包含 mongoexport 的 Windows zip 被 Virustotal 标记为具有 Trojan-PSW.Agent - 所以不要亲自使用该命令。
【解决方案3】:

扩展其他答案:

我发现@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 停止吐出这些 cmets,而只通过传递 --quiet 标志来打印我们要求的内容

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

【讨论】:

  • 编辑他的答案比添加一个新的要好。
【解决方案4】:

您可以尝试以下方法:

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】:

    看看 this

    用于从 mongo shell 输出到文件。 不支持从 mongos shell 输出 csv。您必须自己编写 javascript 或使用可用的众多转换器之一。例如,谷歌“将 json 转换为 csv”。

    【讨论】:

      【解决方案6】:

      只是在这里权衡一下我一直在使用的一个很好的解决方案。这类似于上面的Lucky Soni's solution,因为它支持聚合,但不需要对字段名称进行硬编码。

      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
      

      【讨论】:

        【解决方案7】:

        我使用以下技术。它使列名与内容保持同步变得容易:

        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'))
        

        【讨论】:

          【解决方案8】:

          在远程服务器中执行脚本时。 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

          Linux 版本将使用 grep

          【讨论】:

            猜你喜欢
            • 2021-09-03
            • 2020-06-11
            • 2014-04-29
            • 1970-01-01
            • 1970-01-01
            • 2018-03-25
            • 2015-11-02
            • 1970-01-01
            相关资源
            最近更新 更多