Skip to content

Instantly share code, notes, and snippets.

@Gondrak08
Created February 7, 2023 01:45
Show Gist options
  • Save Gondrak08/1bc7f631490c4b0a72ae51c732d57893 to your computer and use it in GitHub Desktop.
Save Gondrak08/1bc7f631490c4b0a72ae51c732d57893 to your computer and use it in GitHub Desktop.

Como fazer uma rota post para o registro de uma array de objetos?

A intenção deste artigo é te ensinar como manipular uma array de objetos em uma rota post feita em nodejs e mysql.

 

Olá à todos.

Espero que este artigo te encontre bem e, sem mais delongas, vamos direto ao ponto.

Caso você queira saber como criar um pequeno servidor usando Node.js e Mysql clique aqui.

Recentemente estou trabalhando em um aplicativo para entregas e ocorreu-me de lidar com um problema que nunca tive antes. Como eu registro em meu banco de dados uma array de objetos relacionados?

A minha primeira idéia foi simplesmente criar um for onde a cada key da array eu registraria os valores do objeto, porém isso causava um erro na resposta do node.js que até agora, admito, não compreendo o por quê de ocorrer.

Durante este tutorial irei usar algumas imagens exemplificando supostos casos que você terá de arrays de objetos, sinta-se livre para fazer a modificação que quiser.

No mais, vamos direto ao código.


Primeiro Passo

Crie uma tabela em seu database onde será salvo a array de objetos. A minha está assim. Sinta-se livre para modifica-la como bem entender.

create table orders(
    id int NOT NULL AUTO_INCREMENT ,
    uuid varchar(200) NOT NULL,
    storeId int NOT NULL,
    product JSON DEFAULT NULL,
    quantity integer,
    price DECIMAL(10,2) DEFAULT 0.00,
    primary key(id)
);

Peço que presta atenção em dois valores desta tabela.

  • O primeiro sendo storeId. Isto será usado para relacionar a ordem do produto com a loja para qual será enviado.
  • Segundo, product JSON DEFAULT NULL, onde será salvo o produto(objeto) product oriundo de outra tabela, relacionando de forma prática as duas tabelas na chamada do sistema.

ps: não sou especialista em sql, sinta-se livre para comentar abaixo a respetio desta parte.

Uma vez criada a tabela, ela se apresentará assim no MYSQL.

MariaDB [foodstore]> show columns from orders;
+----------+---------------+------+-----+---------+----------------+
| Field    | Type          | Null | Key | Default | Extra          |
+----------+---------------+------+-----+---------+----------------+
| id       | int(11)       | NO   | PRI | NULL    | auto_increment |
| uuid     | varchar(200)  | NO   |     | NULL    |                |
| storeId  | int(11)       | NO   |     | NULL    |                |
| product  | longtext      | YES  |     | NULL    |                |
| quantity | int(11)       | YES  |     | NULL    |                |
| price    | decimal(10,2) | YES  |     | 0.00    |                |
+----------+---------------+------+-----+---------+----------------+

Caso queira saber mais sobre Mysql clique aqui.

Uma vez estabelecida a tabela, passamos para a array de objetos.


O objeto:

A array de objetos que iremos salvar na rota será similar a esta, lembrando que em uma situação real a array será enviada pelo usuário através do frontend de sua aplicação.

const list = [
{
    id:"3845bf3c-a7b0-476d-8a96-c467b7a4a5b7",
    price:2.5,
    quantity:3.5,
    product:{
        storeId:1,
        storeName:"Bbq",
        id:1,
        categoryId:1,
        description:"a delicious product"
        discoutnValue:null,
        price:0.50,
        productImage:....
    }
},
{
    id:"3845bf3c-a7b0-476d-8a96-c467b7a4a5b7",
    price:2.5,
    quantity:3.5,
    product:{
        storeId:1,
        storeName:"Bbq",
        id:1,
        categoryId:1,
        description:"a delicious product"
        discoutnValue:null,
        price:0.50,
        productImage:....
    }
}
....
]

Você pode repetir quantas vezes quiser o objeto dentro da array. Por questão de exemplo, fiz apenas duas vezes.

e agora, a rota.


Criação da Rota

Para salvarmos algo no banco de dados usamos a rota post.

Primeiro irei te mostrar como eu criei a primeira rota, que me trouxe tanta dor de cabeça, e qual o erro que eu recebia do backend:

router.post("/send", (req, res, next)=>{
    const orderDetails = req.body.list;
    const query = "insert into orders (uuid, storeId, product, quantity, price) values(?,?,?,?,?)";
    ....
});

O código acima pode ser dividido em duas partes.

Primeiro crie uma constante para requerir o dado enviado pelo frontend: const ordeDetails = req.body.list, lembrando que list neste caso se refere à array de objetos.

Depois, crie a query que irá inseriri os dados em seu bancos de dados, neste caso MYSQL.

const query = "insert into insert into orders (uuid, storeId, product, quantity, price) values(?,?,?,?,?)

Caso tenha interesse em saber mais sobre a escrita de query.

Agora eu tenho minha query e minha array de objetos, porém como inserir este valor no banco de dado? Se você usar apenas o connection para a realização da chamada, haverá um erro porque você está enviando uma array e o mysql não está esperando por isso. Portanto ele não saberá o que fazer e irá te retornar um erro. Como eu disse acima, a saída então seria a criação de um for e para cada key você passaria os valores requesitados pela query.

ficando assim:

router.post("/send", (req, res, next)=>{
    const orderDetails = req.body.list;
    const query = "insert into orders (uuid, storeId, product, quantity, price) values(?,?,?,?,?)";

    for(let key in orderDetails){
        const productDetail = JSON.stringify(orderDetails[key].product)

        connection.query(query, [orderDetails[key].id, orderDetails[key].product.storeId,productDetail, orderDetails[key].quantity, orderDetails[key].price], (err, result)=>{

            if(!err){

                return res.status(200).json({message: "Order addded successfully"});
            }
                else 
                    return res.status(500).json(err);

        });
    }

});

Desta forma o código irá funcionar, injetando cada objeto dentro da array e os seus respectivos valores dentro do banco de dados. Porém, destá forma, irá ocorrer um erro.

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

O motivo deste erro é porquê o nodejs compreende que você está realizando mais do que um res.json, um retorno dentro de um retorno, e assim ele quebra o sistema. Se você retirar o retorno res o código continua a funcionar, porém o frontend não será avisado do sucesso de sua ação. E então, o que fazer?

Se você está até aqui, parabéns. Desculpe pela demora, mas agora vamos direto ao ponto. Como realizar uma rota post para uma array de objetos em node.js e mysql?

 

Pegando o código acima nós precisaremos apenas modifcarmos pouquíssimas coisas. Uma delas é retirar o for e subsitui-lo por um map que irá retornar uma array com os valores requesitados pela query.

router.post("/send", (req, res, next)=>{
    const orderDetails = req.body.list.map((item)=>[
        item.id,
        item.product.storeId,
        JSON.stringify(item.product),
        item.quantity,
        item.price
    ])
....
}

Lembre-se de usar o JSON.stringifi() para transformar o objeto product em uma string, pois o mysql apenas compreende string, senão haverá um erro e o seu código não ira funcionar no momento de inserir os valores.

Por fim, modificando a query para:

const query = "insert into orders (uuid, storeId, product, quantity, price) values ?";

Desta forma o Mysql sabe o que fazer de forma automática quando for insirdo a array de objetos. Recebendo apenas um valor ? o mysql irá olhar dentro dele e encontrará cada um dos valores necessários para realizar a sua ação.

De resto o código ficará assim.

router.post("/send", (req, res, next)=>{
    const orderDetails = req.body.list.map((item)=>[
        item.id,
        item.product.storeId,
        JSON.stringify(item.product),
        item.quantity,
        item.price
    ]);
    
    const query = "insert into orders (uuid, storeId, product, quantity, price) values ?";

    connection.query(query, [orderDetails],(err, result)=>{
        if(!err){
            return res.status(200).json({message:"it' work!"})
        } else
            return res.status(500).json(err);
    })

});

Agora seu código irá rodar sem problemas.

Espero ter ajudado

Bom código. ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment