Сценарий NodeJS и высокое использование памяти при обработке документов mongodb с помощью jexl

Я создал скрипт nodejs для обработки коллекции продуктов mongodb. Каждый продукт должен обрабатываться с помощью языка выражений jexl. Конечный результат должен быть текстовым файлом со всеми данными о продукте. Сценарий работает, но мне нужна помощь, чтобы оптимизировать его, потому что он занимает много памяти. В скрипте я использую курсор mongodb с размером пакета 1-5, чтобы ограничить количество полученных документов. Запрос получает около 9200 документов со средним размером 8,7 КБ.

С размером пакета в 1 сценарий занимает часы и занимает около 200-600 МБ памяти. Когда я устанавливаю размер пакета ~10, я получаю исключение нехватки памяти. (CALL_AND_RETRY_LAST Распределение не выполнено - процесс исчерпал память).

Я попытался закомментировать jexl.eval, и скрипт запускается через несколько секунд.

У кого-нибудь есть идеи, как оптимизировать этот скрипт? LineTemplate - это объединенная строка всех выражений jexl. Я вырезал эту строку выражения, чтобы сделать весь сценарий более читабельным. Обычно последнее выражение "{{attribute [.id == 1 && .language == ""] в атрибутах? Attribute [.id == 1 && .language == ""].value: ""}}|" повторяется 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;
      });
    });
  });
});

0 ответов

Другие вопросы по тегам