Задать вопрос

Хотелось бы узнать мнение болле опытных разработчиков?

Есть вот такая не простая функция(по моему мнению я долго думал над ней)
function accepting_expenses_array(req, res) {
  const expenses_array = req.body;
  const expenses_as_numbers = expenses_array.map(Number);

  pool.query('SELECT id_work FROM "works" WHERE id_order = $1', [expenses_as_numbers[0]], async (error, results) => {
    if (error) {
      return res.status(500).json({ success: false, error: error.message });
    }
    
    var work_id_array = results.rows.map(row => row.id_work);
    console.log("work_id_array", work_id_array);
    if ((work_id_array.length * 8) !== expenses_as_numbers.slice(1).length) {
      return res.status(400).json({ 
        success: false, 
        error: 'Количество элементов в массиве расходов не соответствует количеству id_work.'
      });
    }

    const expenses_without_first = expenses_as_numbers.slice(1);
    console.log("expenses_without_first", expenses_without_first);

    (async () => { // Оборачиваем код в IIFE для использования async/await
      try {
        const insertQuery = `INSERT INTO "expenses" (
          id_work, 
          type_work_id, 
          printer_id, 
          material_id, 
          performer_id, 
          format_id,
          n_sheets, 
          n_pages, 
          n_ruined
        ) VALUES ${createValuesTemplate(expenses_without_first.length)}`;
        
        const values = [];
        work_id_array.forEach((idWork, index) => {
          values.push(idWork);
          values.push(...expenses_without_first.slice(index * 8, (index + 1) * 8));
        });
        
        // Выполняем запрос
        await pool.query(insertQuery, values);
  
        // Отправляем ответ клиенту, что всё прошло успешно
        res.json({ success: true, message: 'Данные успешно добавлены.' });
      } catch (error) {
        console.error('Error during expenses insertion:', error.stack);
        res.status(500).json({
          success: false,
          error: 'Произошла ошибка при попытке вставки данных: ' + error.message
        });
      }
    })();
});
}

но вот в процессе у меня возник вопрос. А как лучше(правильнее) сделать так чтобы каждая итерация цикла отдельно записывалась в базу данных или сначала сформировать данные для value(как сделано по идее сейчас) и что будет производительнее ?. Не много о данных expenses_without_first.length его длина может варьироваться от 8 до 64. И мне бы хотелось достичь максимальной производительности даже при загруженной бд. К сожалению я совсем новичок в таких вопросах.
  • Вопрос задан
  • 628 просмотров
Подписаться 3 Простой 9 комментариев
Решения вопроса 1
@holllop Автор вопроса
На данный момент переделал функции
function createValuesTemplate(length) {
  const numColumns = 9; 
  const placeholders = [];
  let placeholderIndex = 1; 

  for (let i = 0; i < length; i++) {
    let rowPlaceholders = [];
    for (let j = 0; j < numColumns; j++) {
      rowPlaceholders.push('$' + placeholderIndex++);
    }
    placeholders.push('(' + rowPlaceholders.join(', ') + ')');
  }

  return placeholders.join(', ');
}

async function accepting_expenses_array(req, res) {
  const expenses_array = req.body;
  const expenses_as_numbers = expenses_array.map(Number);
  console.log("expenses_as_numbers",expenses_as_numbers)
  try {
    // Первое число - id_order. Ищем максимальный id_work
    const results = await pool.query('SELECT id_work FROM "works" WHERE id_order = $1', [expenses_as_numbers[0]]);
    
    const work_id_array = results.rows.map(row => row.id_work);
    const work_id_max = Math.max(...work_id_array);
    console.log("work_id_max",work_id_max)

    const expensesWithoutFirst = expenses_as_numbers.slice(1); // Игнорируем первый элемент, id_order

    const newExpensesArray = [];
    for (let i = 0; i < expensesWithoutFirst.length; i += 8) {
      // Добавляем work_id_max в начало каждой строки значений
      newExpensesArray.push(work_id_max, ...expensesWithoutFirst.slice(i, i + 8));
    }
    console.log("newExpensesArray",newExpensesArray)
    if (newExpensesArray.length % 9 !== 0) {
      return res.status(400).json({
        success: false,
        error: 'Количество элементов в массиве расходов должно быть кратным числу столбцов таблицы (включая work_id_max).'
      });
    }
    
    // Подготовка SQL запроса на вставку
    const insertQuery = `INSERT INTO "expenses" (
      n_plan, 
      type_work_id, 
      printer_id, 
      material_id,
      format_id, 
      performer_id, 
      n_sheets, 
      n_page, 
      n_ruined
    ) VALUES ${createValuesTemplate(newExpensesArray.length / 9)};;`

    console.log("createValuesTemplate(newExpensesArray.length / 9)",createValuesTemplate(newExpensesArray.length / 9))

    // Выполняем запрос на вставку с newExpensesArray
    const insertResult = await pool.query(insertQuery, newExpensesArray);
    console.log("insertResult",insertResult);
    // Отправляем успешный ответ
    return res.json({ success: true, message: 'Данные успешно добавлены.' });
  } catch (error) {
    // Логирование ошибки и отправка ошибочного ответа
    console.error('Error during query execution:', error.stack);
    return res.status(500).json({
      success: false,
      error: error.message
    });
  }
}

выяснил что пакетная вставка быстрее
Добил до конца, то что хотел. Работает как задумано
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
2ord
@2ord
Первое, что я бы сделал в этой функции - это раздробил бы на множество мелких.
Нужно избавиться от вложенного кода.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы