【问题标题】:Process 10 GB JSON file in Node JS在 Node JS 中处理 10 GB JSON 文件
【发布时间】:2021-10-26 05:26:58
【问题描述】:

我有一个json文件,该文件的结构如下:

{
"orders":[
 {
  "id": 876876876,
  "app_id":580714,
  "client_details": {},
  "discount_codes": [{}],
  "line_items": [
        {
          "id": 466157049,
          ...
        }
   ],
   ...... 
 },
 {
   "id": 47844583,
   "app_id":580714,
   "client_details": {},
   "discount_codes": [{}],
   "line_items": [
        {
          "id": 466157049,
           ...
        }],
     ....
 },
 {...},
 {...},
 {...}
 ]
}

这个数组可以包含超过 100 万(100 万)个对象。目前我需要:

  • 查找具有订单 ID 的对象
  • 订单总数
  • 获取带有订单id和数量限制的订单

我正在使用以下代码:

 return new Promise((resolve, reject) => {
        var orders = []
        var getStream = function () {
            var stream = fs.createReadStream(file_path, { encoding: 'utf8' }),
                parser = JSONStream.parse('*');
            return stream.pipe(parser);
        };
    
        getStream()
        .pipe(es.mapSync(function (data) {
            
            orders = data
        })) .on('end', function() {
            
            resolve(orders)

        })
})

但这会使系统挂起。另外,我也使用了以下命令:

 node --max-old-space-size=8192 index.js

但这也行不通。谁能帮我处理这么大的json文件。

已编辑现在文件大小为 850MB,我正在使用以下代码:

return new Promise((resolve, reject) => {
  var data = ''
        var reader_stream = fs.createReadStream(file_path) 
        reader_stream.setEncoding('UTF8')

        reader_stream.on('data', function(chunk) {
            data += chunk
        })

        reader_stream.on('end',function() {
            try{
                const orders_result = JSON.parse(data)
                var order_count     = (orders_result.orders)

                resolve({
                    "count": order_count.length
                })
            } catch(err) {
                console.log(err)
            }
        })

        reader_stream.on('error', function(err) {
            console.log(err.stack)
            reject(err.stack)
        })
})

并得到以下错误

未捕获的异常:RangeError:无效的字符串长度

【问题讨论】:

  • 当您拥有如此大量的数据时,将其存储在数据库中可能是一个好主意。您可以从中查询您需要的内容。
  • 我知道@Sandsten,但 DB 不是这里的选项。
  • 什么是“不工作”?
  • @DeepKakkar - 10GB JSON 需要 >10GB 内存用于您的节点进程 - 我认为您的节​​点进程在 64 位操作系统中是 64 位的,对吧?
  • @DeepKakkar,我想你正在寻找这个question 并且可能在那里重复。

标签: javascript node.js arrays fs


【解决方案1】:

JSON.parse 需要将整个文件读入内存,包括应用程序不需要的部分。一种方法是使用类似 SAX 的解析器,例如 clarinet。这些解析器不会将整个文件读入内存,它们会在解析过程中生成事件。您需要处理这些事件以检查数据是否感兴趣,并仅存储您实际需要的信息。

这会减少解析过程所需的内存量,但不是那么方便。你的操作听起来你不需要所有的数据,所以也许你很幸运,一个精简的版本可以放入内存。

【讨论】:

  • 我已经编辑了我的问题,现在文件大小只有 850 MB,但出现错误为 __RangeError: Invalid string length
  • @DeepKakkar 这个答案应该仍然可以解决问题。字符串有大小限制,因此您将不得不使用真正的数据库,将数据拆分为较小的文件(将它们分类到多个文件夹中?),或者使用解析器,就像这个答案中的解析器一样。
  • 在不知道您的确切设置的情况下,一个 850MB 的字符串仍然可能超出您的应用程序的处理能力。这也取决于您的 node.js 版本,请参阅答案(尤其是评论):stackoverflow.com/a/47781288/431715
  • 我使用的是v14.15.0版本的Node js
  • 我没有得到示例代码来使用,因此我可以获得对象进行处理。例如var stream = require("clarinet").createStream(options);那里有什么选择?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-24
相关资源
最近更新 更多