#node.js #express
#node.js #выразить
Вопрос:
Мне нужен совет о том, как структурировать эту функцию, поскольку на данный момент это происходит не в правильном порядке из-за асинхронности узла.
Это тот поток, которого я хочу достичь; Мне нужна помощь не с самим кодом, а с порядком достижения конечных результатов и любыми предложениями о том, как сделать его эффективным
- Узел направляет запрос GET на мой контроллер.
- Контроллер считывает файл .csv в локальной системе и открывает поток чтения с помощью модуля fs
- Затем используйте модуль csv-parse, чтобы преобразовать его в массив построчно (много 100 000 строк)
- Запустите блок try / catch
- Используя текущую строку из csv, возьмите значение и попытайтесь найти его в MongoDB
- Если он найден, возьмите идентификатор и сохраните строку из CSV и этот идентификатор как внешний идентификатор в отдельной базе данных
- Если не найден, создайте запись в БД и возьмите новый идентификатор, а затем выполните 6.
- Распечатайте на терминале номер строки, над которым выполняется обработка (в идеале в какой-то момент я хотел бы иметь возможность отправлять это значение на страницу и обновлять его как индикатор выполнения по мере завершения строк)
Вот небольшая часть структуры кода, которую я использую в настоящее время;
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 /