首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >批量合并文件以进行mongoimport的Bash循环

批量合并文件以进行mongoimport的Bash循环
EN

Stack Overflow用户
提问于 2017-01-18 19:49:12
回答 2查看 420关注 0票数 3

我有一个目录,里面有250万个小JSON文件。它在磁盘上有104 It。它们是多行文件。

我想从这些文件创建一组JSON数组,这样我就可以在合理的时间内使用mongoimport导入它们。文件大小不能超过16mb,但即使我设法将它们分成10个一组,我也会很高兴。

到目前为止,我可以使用这个以大约1000/分钟的速度一次完成一个:

代码语言:javascript
复制
for i in *.json; do mongoimport --writeConcern 0 --db mydb --collection all --quiet --file $i; done

我想我可以使用" jq“来做这件事,但是我不知道如何让bash循环一次向jq传递10个文件。请注意,使用bash find会导致错误,因为文件太多。

使用jq,您可以使用--slurp创建数组,使用-c创建多行json单行。但是,我不知道如何将这两个命令合并为一个命令。

如果可能,请帮助解决问题的两个部分。

EN

回答 2

Stack Overflow用户

发布于 2017-01-18 20:40:56

这里有一种方法。为了说明这一点,我使用了awk,因为它可以小批量读取文件列表,并且能够执行jq和mongoimport。您可能需要进行一些调整,以使整个系统更加健壮,测试错误,等等。

这个想法要么是生成一个可以查看然后执行的脚本,要么是使用awk的system()命令直接执行命令。首先,让我们生成脚本:

代码语言:javascript
复制
 ls *.json | awk -v group=10 -v tmpfile=json.tmp '
  function out() {
    print "jq -s . " files " > " tmpfile;
    print "mongoimport --writeConcern 0 --db mydb --collection all --quiet --file " tmpfile;
    print "rm " tmpfile;
    files="";
  }
  BEGIN {n=1; files="";
    print "test -r " tmpfile " && rm " tmpfile;
  }
  n % group == 0 {
    out();
  }
  { files = files " \""$0 "\"";
    n++;
  }
  END { if (files) {out();}}
'

一旦验证了它的有效性,您就可以执行生成的脚本,或者更改"print ...“要使用"system(....)“的行

使用jq生成脚本

下面是一个仅用于jq的脚本生成方法。由于文件数量非常大,下面的代码使用的是jq 1.5中才引入的功能,所以它的内存使用与上面的awk脚本类似:

代码语言:javascript
复制
def read(n):
  # state: [answer, hold]
  foreach (inputs, null) as $i
    ([null, null];
     if $i == null then .[0] = .[1] 
       elif .[1]|length == n then [.[1],[$i]] 
       else [null, .[1] + [$i]]
       end;
     .[0] | select(.) );

"test -r json.tmp && rm json.tmp",
 (read($group|tonumber)
 | map("\"\(.)\"") 
 | join(" ")
 | ("jq -s . \(.) > json.tmp", mongo("json.tmp"), "rm json.tmp") )

调用:

代码语言:javascript
复制
ls *.json | jq -nRr --arg group 10 -f generate.jq
票数 2
EN

Stack Overflow用户

发布于 2017-01-18 22:39:52

这是我想出来的。它似乎起作用了,正在以大约每秒80的速度导入到外部硬盘驱动器中。

代码语言:javascript
复制
#!/bin/bash
files=(*.json)
for((I=0;I<${#files[*]};I+=500)); do jq -c '.' ${files[@]:I:500} | mongoimport --writeConcern 0 --numInsertionWorkers 16 --db mydb --collection all --quiet;echo $I; done

然而,有些是失败的。我已经导入了105k的文件,但只有98547个出现在mongo集合中。我想是因为有些文档大于16mb。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41718679

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档