新しい形式にマップして新しい DB にアップロードする必要がある非常に大きな (> 500MB) JSON ファイルがいくつかあります。
古い形式:
{
id: '001',
timestamp: 2016-06-02T14:10:53Z,
contentLength: 123456,
filepath: 'original/...',
size: 'original'
},
{
id: '001',
timestamp: 2016-06-02T14:10:53Z,
contentLength: 24565,
filepath: 'medium/...',
size: 'medium'
},
{
id: '001',
timestamp: 2016-06-02T14:10:53Z,
contentLength: 5464,
filepath: 'small/...',
size: 'small'
}
新しいフォーマット:
{
Id: '001',
Timestamp: 2016-06-02T14:10:53Z,
OriginalSize: {
ContentLength: 123456,
FilePath: 'original/...'
},
MediumSize: {
ContentLength: 24565,
FilePath: 'medium/...'
},
SmallSize: {
ContentLength: 5464,
FilePath: 'small/...'
}
}
最初に「元の」サイズを処理して、このような小さなデータセットでこれを達成していました:
let out = data.filter(o => o.size === 'original).map(o => {
return {
Id: o.id,
Timestamp: o.timestamp,
OriginalSize: {
ContentLength: o.contentLength,
FilePath: o.filepath
}
};
});
data.filter(o => o.size !== 'original').forEach(o => {
let orig = out.find(function (og) {
return og.Timestamp === o.timestamp;
});
orig[o.size + 'Size'] = {
ContentLength: o.contentLength,
FilePath: o.filepath
};
)
// out now contains the correctly-formatted objects
問題は非常に大きなデータセットにあり、数百メガバイトの JSON を一度にメモリにロードすることはできません。これはストリームを使用する絶好の機会のように思えますが、もちろん、ファイルをチャンクで読み取る場合、小さな配列で .find() を実行して「元の」サイズを見つけることはできません。ファイル全体をスキャンしてオリジナルを見つけ、もう一度スキャンして見つかったものに他のサイズを追加すると、とにかくデータセット全体がメモリに保存されます。
オブジェクトの単純な 1 対 1 の再マッピングを行っていた場合、これは素晴らしいことです。
確かに、この種の問題に遭遇するのは私が最初ではありません。過去にどのようなソリューションが使用されましたか? どうすればこれにアプローチできますか?