【发布时间】:2016-10-02 09:12:56
【问题描述】:
我有一些非常大 (> 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() 以查找“原始”大小将不起作用。如果我扫描整个文件以找到原始文件,然后再次扫描以将其他大小添加到我找到的文件中,无论如何我最终都会将整个数据集放在内存中。
我知道JSONStream,如果我对我的对象进行简单的 1-1 重新映射,那就太好了。
当然,我不可能是第一个遇到这种问题的人。过去使用了哪些解决方案?我该如何处理?
【问题讨论】:
-
输入数组中不同维度的对象不是总是相邻吗?
-
您确定要通过它们的时间戳而不是它们的 id 来匹配它们吗?
-
我的例子可能具有误导性。不,不幸的是,这些对象根本不相邻,并且可能位于文件中的任何位置。是的,按时间戳匹配是我想要的。这是对具有特定 ID 的所有记录进行操作,因此在这里并不太重要。
-
每个属性是否都在自己的行中,如您的问题中所述?例如,
id在一行,timestamp在下一行,等等 -
不,每个对象一行一行。
标签: javascript node.js node-streams