NodeJS脚本和使用jexl处理mongodb文档时的高内存使用率

我已经创build了一个nodejs脚本来处理一个mongodb产品集合。 每个产品都需要使用expression式语言jexl来处理。 最终结果应该是包含所有产品数据的文本文件。 该脚本的作品,但我需要一些帮助来优化它,因为它消耗了大量的内存。 在脚本中,我使用了一个批量为1-5的mongodb光标来限制接收到的文档。 查询接收约9200个文件,平均大小为8.7KB。

使用1的批处理大小需要花费大约200-600 MB的内存。 当我设置批量大小为〜10我得到一个内存不足的例外。 (CALL_AND_RETRY_LAST分配失败 – 进程内存不足)。

我已经试图将jexl.eval注释掉,脚本在几秒钟内运行。

有人有一个想法如何优化这个脚本? lineTemplate是所有jexlexpression式的连接string。 我剪切了这个expression式string,使整个脚本更具可读性。 通常情况下,最后一个expression式“{{attributes [.id == 1 && .language ==”“]属性中的属性是[.id == 1 && .language ==”“] .value:”“}} |” 用不同的ID重复106次。

var async = require("async"); var lineTemplate = '{{no}}|Parent_ID|{{no}}|{{translations[.language == "DE-DE"] in translations ? translations[.language == "DE-DE"].title : ""}}|{{prices[.channel == "DE" && .specialPrice == false] in prices ? prices[.channel == "DE" && .specialPrice == false].price : ""}}|{{prices[.channel == "DE" && .specialPrice == true] in prices ? prices[.channel == "DE" && .specialPrice == true].price : ""}}|{{itemCategory}}|{{productGroup}}|{{groupOfGoods}}|http://www.google.de/test.html|{{crossReferenceNo}}|{{brand}}|Replenishment_in_days|Quantity_in_Stock|Availability|EUR|{{attributes[.id == 1 && .language == ""] in attributes ? attributes[.id == 1 && .language == ""].value : ""}}| ... \r\n' var MongoClient = require('mongodb').MongoClient , assert = require('assert'); var fs = require('fs'); var filename = '/tmp/products.txt'; fs.writeFileSync(filename, 'no;name;price\r\n'); function ProcessProduct(product, expression, cb) { var jexl = require('Jexl'); var regex = /{{([^{}]*)}}/g; var line = lineTemplate; var matches = lineTemplate.match(regex); async.each(matches, function(match, callback){ var query = match.substring(2, match.length - 2); jexl.eval(query, product, function(err, res) { if(err) console.log(err); //console.log(res); var strToReplace = "{{" + query + "}}"; line = line.replace(strToReplace, res); callback(); }); }, function(err){ delete(jexl); if(err) return cb(err, null); cb(null, line); } ); } var url = 'mongodb://localhost/test'; MongoClient.connect(url, function(err, db) { assert.equal(null, err); console.log("Connected correctly to server"); var collection = db.collection('products'); var cursor = collection.find({ "saleschannel": { $elemMatch: { "channel": "DE" } }}, { "batchSize": 1, fields: {} }).each(function(err, product) { ProcessProduct(product, lineTemplate, function(err, data) { fs.appendFile(filename, data, function(err) { if (err) throw err; }); }); }); });