在 Node JS 中处理 10 GB JSON 文件

Posted

技术标签:

【中文标题】在 Node JS 中处理 10 GB JSON 文件【英文标题】:Process 10 GB JSON file in Node JS 【发布时间】: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 并且可能在那里重复。 【参考方案1】:

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

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

【讨论】:

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

以上是关于在 Node JS 中处理 10 GB JSON 文件的主要内容,如果未能解决你的问题,请参考以下文章

为啥 node.js 配置文件的大小会是数 GB? webstorm 处理的方式

Node.js处理I/O数据之Buffer模块缓冲数据

Node.js Express 应用程序在负载测试下花费太多时间来处理出站 HTTP 请求

解析巨大(10GB+)JSON 文件的最佳方式

如何读取真正大的 JSON 文件并使用 node.js 将该文件的数据插入 MYSQL 数据库?

如何在 node.js + Express 中同时支持 json 和 jsonp 响应?