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

    @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
        });
      }
    }

    выяснил что пакетная вставка быстрее
    Добил до конца, то что хотел. Работает как задумано
    Ответ написан
    Комментировать
  • Как составить сложный агрегированный запрос?

    @holllop Автор вопроса
    Правильный sql запрос для того чтобы реализовать, то что я хотел выглядит так
    SELECT 
          o.order_id, 
          d.name AS dname, 
          c.customer, 
          o.date, 
          array_agg(
            json_build_object(
              'id_works', w.id_work::text, 
              'name_object', w.name_object, 
              'work_items', subq.work_items
            )
          ) AS works_info
          FROM "order" o
          JOIN works w ON o.order_id = w.id_order
          JOIN departaments d ON o.departament_id = d.departament_id
          JOIN customers c ON o.customer_id = c.customer_id
          LEFT JOIN (
            SELECT
                w.id_work,
                w.name_object,
                json_agg(json_build_object(
                    'n_works', e.n_work::text,
                    'type_works', tw.type_work,
                    'printers', pr.printer,
                    'materials', ma.material,
                    'performers', pe.performer,
                    'formats', f.format,
                    'n_sheets', e.n_sheets::text
                )) AS work_items
            FROM works w
            LEFT JOIN expenses e ON w.id_work = e.n_plan
            LEFT JOIN type_work tw ON e.type_work_id = tw.type_work_id
            LEFT JOIN printer pr ON e.printer_id = pr.printer_id
            LEFT JOIN material ma ON e.material_id = ma.material_id
            LEFT JOIN performers pe ON e.performer_id = pe.performer_id
            LEFT JOIN format f ON e.format_id = f.format_id
            GROUP BY w.id_work, w.name_object
          ) AS subq ON w.id_work = subq.id_work
        GROUP BY o.order_id, d.name, c.customer, o.date
    Ответ написан
    Комментировать
  • Как обеспечить возможность одновременного вызова эндпойнта, пишущего в БД?

    @holllop
    Попытаюсь ответить как-то комплексно.
    Дедлоки в базе данных могут быть вызваны различными причинами, такими как конфликты параллельных транзакций, блокировки на ресурсы и другие. В вашем случае, если у вас возникают дедлоки при одновременных запросах, использование транзакций может помочь, но вам также необходимо управлять блокировками и избегать конфликтов. То есть воспользоваться блокировкой на уровне строки (Row Locking) и блокировкой на уровне транзакции (Transaction Locking) это всё механизмы Sequelize. Вполне возможно, что даже при использовании этих механизмов могут остаться дедлоки. И в таком случае использование Redis будет необходимо.
    Ответ написан
    2 комментария
  • Как правильно сделать сложный запрос к БД, через Node.js?

    @holllop Автор вопроса
    Прежде чем ответить, хочу поблагодарить kosuha. Ты мне очень помог реально. Как оказалось мне не нужна сложная структура типа GET запрос зависящий от POST запроса(из-за чего у меня и возникала ошибка
    TypeError: Converting circular structure to JSON
        --> starting at object with constructor 'Socket'
        |     property 'parser' -> object with constructor 'HTTPParser'
        --- property 'socket' closes the circle
    )
    дальше я приведу как я решил свою проблему
    клиент-код
    function loadSelectOptions2(url, selectElement) {
      fetch(url)
        .then(response => response.json())
        .then(data => {
          data.forEach(item => {
            const option = createOption(item.printer_id, item.material);
            selectElement.appendChild(option);
          });
        })
        .catch(error => {
          console.error(error);
          // Обработать ошибку
        });
    }
    selectElement2.addEventListener('change', () => {
        const selectedPrinterId = selectElement2.value;
        console.log('selectedPrinterId:', selectedPrinterId);
        // Очистить select3 перед загрузкой новых опций
        selectElement3.innerHTML = '';
        // Загрузить опции для select3 на основе выбранного значения select2
        if (selectedPrinterId) {
          const url = `http://:3000/printer_material?printer_id=${encodeURIComponent(selectedPrinterId)}`;
          loadSelectOptions2(url, selectElement3);
        }
      });

    код сервера
    const http = require('http');
    const express = require('express');
    const bodyParser = require('body-parser');
    const cors = require('cors');
    const db = require('./pool');
    
    const app = express();
    const port = 3000;
    
    app.use(bodyParser.json());
    app.use(
      bodyParser.urlencoded({
        extended: true,
      })
    );
    app.use(cors());
    app.get('/printer_material', (req, res) => {
      const printer_id = parseInt(req.query.printer_id, 10);
    
      console.log('Received printer_id:', printer_id); // Вывод значения в консоль как число
    
      db.getPrinter_material(printer_id, res);
    });
    http.createServer(app).listen(port, () => {
      console.log(`App running on port ${port}.`);
    });

    //pool.js
    const { response } = require('express');
    
    const Pool = require('pg').Pool;
    const pool = new Pool({
      user: '',
      host: '',
      database: '',
      password: '',
      port: 5432,
    });
    
    const getPrinter_material = (printer_id, response) => {
      console.log('Received printer_id:', printer_id); 
    
      pool.connect((error, client, release) => {
        if (error) {
          throw error;
        }
    
        const query = {
          text: `SELECT pr.printer_id, m.material FROM printer_material pm JOIN printer pr ON pm.printer_id = pr.printer_id JOIN material m ON pm.material_id = m.material_id WHERE pr.printer_id = $1`,
          values: [printer_id],
        };
    
        console.log('Query text:', query.text);
    
        client.query(query, (error, results) => {
          release();
    
          if (error) {
            throw error;
          }
    
          console.log(results.rows);
          response.json(results.rows);
        });
      });
    };
    module.exports = {
      getPrinter_material,
    };

    Я не убирал множественные console.log пока они остались так как я часть за частью проверял работоспособность кода
    Ответ написан
    Комментировать