Правильный способ организовать этот процесс в узле

#node.js #express

#node.js #выразить

Вопрос:

Мне нужен совет о том, как структурировать эту функцию, поскольку на данный момент это происходит не в правильном порядке из-за асинхронности узла.

Это тот поток, которого я хочу достичь; Мне нужна помощь не с самим кодом, а с порядком достижения конечных результатов и любыми предложениями о том, как сделать его эффективным

  1. Узел направляет запрос GET на мой контроллер.
  2. Контроллер считывает файл .csv в локальной системе и открывает поток чтения с помощью модуля fs
  3. Затем используйте модуль csv-parse, чтобы преобразовать его в массив построчно (много 100 000 строк)
  4. Запустите блок try / catch
  5. Используя текущую строку из csv, возьмите значение и попытайтесь найти его в MongoDB
  6. Если он найден, возьмите идентификатор и сохраните строку из CSV и этот идентификатор как внешний идентификатор в отдельной базе данных
  7. Если не найден, создайте запись в БД и возьмите новый идентификатор, а затем выполните 6.
  8. Распечатайте на терминале номер строки, над которым выполняется обработка (в идеале в какой-то момент я хотел бы иметь возможность отправлять это значение на страницу и обновлять его как индикатор выполнения по мере завершения строк)

Вот небольшая часть структуры кода, которую я использую в настоящее время;

 const fs = require('fs');
const parse = require('csv-parse');

function addDataOne(req, id) {
  const modelOneInstance = new InstanceOne({ ...code });
  const resultOne = modelOneInstance.save();
  return resultOne;
}
function addDataTwo(req, id) {
  const modelTwoInstance = new InstanceTwo({ ...code });
  const resultTwo = modelTwoInstance.save();
  return resultTwo;
}

exports.add_data = (req, res) => {
  const fileSys = 'public/data/';
  const parsedData = [];
  let i = 0;
  fs.createReadStream(`${fileSys}${req.query.file}`)
    .pipe(parse({}))
    .on('data', (dataRow) => {
      let RowObj = {
        one: dataRow[0],
        two: dataRow[1],
        three: dataRow[2],
        etc,
        etc
      };
      try {
        ModelOne.find(
          { propertyone: RowObj.one, propertytwo: RowObj.two },
          '_id, foreign_id'
        ).exec((err, searchProp) => {
          if (err) {
            console.log(err);
          } else {
            if (searchProp.length > 1) {
              console.log('too many returned from find function');
            }
            if (searchProp.length === 1) {
              addDataOne(RowObj, searchProp[0]).then((result) => {
                searchProp[0].foreign_id.push(result._id);
                searchProp[0].save();
              });
            }
            if (searchProp.length === 0) {
              let resultAddProp = null;
              addDataTwo(RowObj).then((result) => {
                resultAddProp = resu<
                addDataOne(req, resultAddProp._id).then((result) => {
                  resultAddProp.foreign_id.push(result._id);
                  resultAddProp.save();
                });
              });
            }
          }
        });
      } catch (error) {
        console.log(error);
      }
      i  ;
      let iString = i.toString();
      process.stdout.clearLine();
      process.stdout.cursorTo(0);
      process.stdout.write(iString);
    })
    .on('end', () => {
      res.send('added');
    });
};

 

Я пытался заставить функции использовать async / await, но, похоже, это противоречит функциям синтаксического анализа fs.openReadStream или csv, вероятно, из-за моей неопытности и неправильного использования кода…

Я ценю, что это длинный вопрос об основах кода, но были бы оценены лишь некоторые советы / рекомендации / указания о том, как это сделать. У меня это работало, когда данные отправлялись по одному через post-запрос от postman, но я не могу реализовать следующий этап, который заключается в чтении из файла csv, который содержит много записей

Ответ №1:

Прежде всего, вы можете выполнить следующие проверки в одном запросе:

if (searchProp.length === 1) {
if (searchProp.length === 0) {

Используйте опцию upsert в запросе mongodb findOneAndUpdate для обновления или обновления.

Во-вторых, не делайте этого в основном потоке. Используйте механизм очереди, это будет намного эффективнее. Очередь, которую я лично использую, — это Bull Queue .

https://github.com/OptimalBits/bull#basic-usage

Это также обеспечивает функциональность, необходимую для отображения прогресса.

Кроме того, что касается использования Async Await с ReadStream, в сети можно найти множество примеров, таких как: https://humanwhocodes.com/snippets/2019/05/nodejs-read-stream-promise /