一尘不染

jq可以跨文件执行聚合

elasticsearch

我正在尝试确定一个程序/软件,该程序/软件将使我能够有效地提取大量大型CSV文件(总计40+
GB),并输出具有导入到Elasticsearch(ES)所需的特定格式的JSON文件。

jq可以有效地获取如下数据:

file1:
id,age,gender,wave
1,49,M,1
2,72,F,0

file2:
id,time,event1
1,4/20/2095,V39
1,4/21/2095,T21
2,5/17/2094,V39

按ID进行汇总(这样,多个文件中CSV行中的所有JSON文档都属于一个id条目),输出如下所示:

{"index":{"_index":"forum_mat","_type":"subject","_id":"1"}}
{"id":"1","file1":[{"filen":"file1","id":"1","age":"49","gender":"M","wave":"1"}],"file2":[{"filen":"file2","id":"1","time":"4/20/2095","event1":"V39"},{"filen":"file2","id":"1","time":"4/21/2095","event1":"T21"}]}
{"index":{"_index":"forum_mat","_type":"subject","_id":"2"}}
{"id":"2","file1":[{"filen":"file1","id":"2","age":"72","gender":"F","wave":"0"}],"file2":[{"filen":"file2","id":"2","time":"5/17/2094","event1":"V39"}]}

我用Matlab编写了一个脚本,但由于担心它的执行速度慢得多。我可能需要花费数月的时间来处理所有40
GB以上的数据。有人告诉我Logstash(ES首选的数据输入工具)在这种类型的聚合上并不擅长。


阅读 222

收藏
2020-06-22

共1个答案

一尘不染

正如其中一项注释中所建议的那样,我最终使用SQL以我所需的格式导出JSON。另一个线程大有帮助。最后,我选择将给定的SQL表输出到其自己的JSON文件中,而不是将它们组合在一起(文件大小变得难以管理)。这样做的代码结构是这样的,您可以为Bulk
API和JSON数据行生成命令行:

create or replace function format_data_line(command text, data_str text)
returns setof text language plpgsql as $$
begin
    return next command;
    return next             
        replace(
            regexp_replace(data_str,
                '(\d\d\d\d-\d\d-\d\d)T', '\1 ', 'g'),
            e' \n ', '');
end $$;

COPY (
    with f_1 as(
       SELECT id, json_agg(fileX.*) AS tag
       FROM forum.file3
       GROUP BY id
    )
    SELECT 
        format_data_line(
            format('{"update":{"_index":"forum2","_type":"subject","_id":%s}}',a.id),
            format('{"doc":{"id":%s,"fileX":%s}}', 
                a.id, a.tag))
    FROM f_1 a 
) TO '/path/to/json/fileX.json';

使用Bulk
API导入较大的文件也存在问题(内存不足Java错误),因此在特定时间只需要脚本就可以将数据的子集发送到Curl(在Elasticsearch中建立索引)。该脚本的基本结构为:

#!/bin/bash

FILE=$1
INC=100
numline=`wc -l $FILE | awk '{print $1}'`
rm -f output/$FILE.txt
for i in `seq 1 $INC $numline`; do
    TIME=`date +%H:%M:%S`
    echo "[$TIME] Processing lines from $i to $((i + INC -1))"
    rm -f intermediates/interm_file_$i.json
    sed -n $i,$((i +INC - 1))p $FILE >> intermediates/interm_file_$i.json
    curl -s -XPOST localhost:9200/_bulk --data-binary @intermediates/interm_file_$i.json >> output/$FILE.txt
done

应在脚本文件目录下创建一个“中间”目录。该脚本可以另存为“ ESscript”,并在命令行上运行:

./ESscript fileX.json
2020-06-22