web-dev-qa-db-ja.com

Nodejsで大きなJSONファイルを解析し、各オブジェクトを個別に処理します

Nodejsで大きなJSONファイル(約630MB)を読み取り、各オブジェクトをMongoDBに挿入する必要があります。

ここで答えを読みました: Nodejsで大きなJSONファイルを解析

ただし、答えはJSONファイルをオブジェクトごとに処理するのではなく、行ごとに処理することです。したがって、このファイルからオブジェクトを取得して操作する方法はまだわかりません。

JSONファイルには、この種類のオブジェクトが約100,000個あります。

データ形式:

[
  {
    "id": "0000000",
    "name": "Donna Blak",
    "livingSuburb": "Tingalpa",
    "age": 53,
    "nearestHospital": "Royal Children's Hospital",
    "treatments": {
        "19890803": {
            "medicine": "Stomach flu B",
            "disease": "Stomach flu"
        },
        "19740112": {
            "medicine": "Progeria C",
            "disease": "Progeria"
        },
        "19830206": {
            "medicine": "Poliomyelitis B",
            "disease": "Poliomyelitis"
        }
    },
    "class": "patient"
  },
 ...
]

乾杯、

アレックス

19
Lixing Liang

'stream-json' という名前のNiceモジュールがあります。

使用可能なメモリをはるかに超えるJSONファイルを解析できます。

そして

StreamArrayは、頻繁に使用されるケースを処理します。Djangoが作成したデータベースダンプに似た、比較的小さなオブジェクトの巨大な配列です。配列コンポーネントを個別にストリーミングして、それらを自動的に組み立てます。

非常に基本的な例を次に示します。

_const StreamArray = require('stream-json/streamers/StreamArray');
const path = require('path');
const fs = require('fs');

const jsonStream = StreamArray.withParser();

//You'll get json objects here
//Key is an array-index here
jsonStream.on('data', ({key, value}) => {
    console.log(key, value);
});

jsonStream.on('end', () => {
    console.log('All done');
});

const filename = path.join(__dirname, 'sample.json');
fs.createReadStream(filename).pipe(jsonStream.input);_

より複雑な何かをしたい場合1つのオブジェクトを順番に処理し(順序を維持して)、各オブジェクトに非同期操作を適用すると、次のようにカスタムの書き込み可能なストリームを実行できます。

_const StreamArray = require('stream-json/streamers/StreamArray');
const {Writable} = require('stream');
const path = require('path');
const fs = require('fs');

const fileStream = fs.createReadStream(path.join(__dirname, 'sample.json'));
const jsonStream = StreamArray.withParser();

const processingStream = new Writable({
    write({key, value}, encoding, callback) {
        //Save to mongo or do any other async actions

        setTimeout(() => {
            console.log(value);
            //Next record will be read only current one is fully processed
            callback();
        }, 1000);
    },
    //Don't skip this, as we need to operate with objects, not buffers
    objectMode: true
});

//Pipe the streams as follows
fileStream.pipe(jsonStream.input);
jsonStream.pipe(processingStream);

//So we're waiting for the 'finish' event when everything is done.
processingStream.on('finish', () => console.log('All done'));_

注意:上記の例は、 'stream-json @ 1.1.3'でテストされています。一部の以前のバージョン(1.0.0より前のバージョン)では、次のことが必要になる場合があります。

const StreamArray = require('stream-json/utils/StreamArray');

その後

const jsonStream = StreamArray.make();

30