Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

240
Visualizações
Bash loop to merge files in batches for mongoimport

I have a directory with 2.5 million small JSON files in it. It's 104gb on disk. They're multi-line files.

I would like to create a set of JSON arrays from the files so that I can import them using mongoimport in a reasonable amount of time. The files can be no bigger than 16mb, but I'd be happy even if I managed to get them in sets of ten.

So far, I can use this to do them one at a time at about 1000/minute:

for i in *.json; do mongoimport --writeConcern 0 --db mydb --collection all --quiet --file $i; done

I think I can use "jq" to do this, but I have no idea how to make the bash loop pass 10 files at a time to jq. Note that using bash find results in an error as there are too many files.

With jq you can use --slurp to create arrays, and -c to make multiline json single line. However, I can't see how to combine the two into a single command.

Please help with both parts of the problem if possible.

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

Here's one approach. To illustrate, I've used awk as it can read the list of files in small batches and because it has the ability to execute jq and mongoimport. You will probably need to make some adjustments to make the whole thing more robust, to test for errors, and so on.

The idea is either to generate a script that can be reviewed and then executed, or to use awk's system() command to execute the commands directly. First, let's generate the script:

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

Once you've verified this works, you can either execute the generated script, or change the "print ..." lines to use "system(....)"

Using jq to generate the script

Here's a jq-only approach for generating the script. Since the number of files is very large, the following uses features that were only introduced in jq 1.5, so its memory usage is similar to the awk script above:

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

Invocation:

ls *.json | jq -nRr --arg group 10 -f generate.jq
over 4 years ago · Santiago Trujillo Relatório

0

Here is what I came up with. It seems to work and is importing at roughly 80 a second into an external hard drive.

#!/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

However, some are failing. I've imported 105k files but only 98547 appeared in the mongo collection. I think it's because some documents are > 16mb.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda