Come aggiornare un record usando sequelize for node?


117

Sto creando un'API RESTful con NodeJS, express, express-resource e Sequelize che viene utilizzata per gestire i set di dati archiviati in un database MySQL.

Sto cercando di capire come aggiornare correttamente un record usando Sequelize.

Creo un modello:

module.exports = function (sequelize, DataTypes) {
  return sequelize.define('Locale', {
    id: {
      type: DataTypes.INTEGER,
      autoIncrement: true,
      primaryKey: true
    },
    locale: {
      type: DataTypes.STRING,
      allowNull: false,
      unique: true,
      validate: {
        len: 2
      }
    },
    visible: {
      type: DataTypes.BOOLEAN,
      defaultValue: 1
    }
  })
}

Quindi, nel controller delle risorse, definisco un'azione di aggiornamento.

Qui voglio essere in grado di aggiornare il record in cui l'id corrisponde a una req.paramsvariabile.

Per prima cosa costruisco un modello e poi utilizzo il updateAttributesmetodo per aggiornare il record.

const Sequelize = require('sequelize')
const { dbconfig } = require('../config.js')

// Initialize database connection
const sequelize = new Sequelize(dbconfig.database, dbconfig.username, dbconfig.password)

// Locale model
const Locales = sequelize.import(__dirname + './models/Locale')

// Create schema if necessary
Locales.sync()


/**
 * PUT /locale/:id
 */

exports.update = function (req, res) {
  if (req.body.name) {
    const loc = Locales.build()

    loc.updateAttributes({
      locale: req.body.name
    })
      .on('success', id => {
        res.json({
          success: true
        }, 200)
      })
      .on('failure', error => {
        throw new Error(error)
      })
  }
  else
    throw new Error('Data not provided')
}

Ora, questo non produce effettivamente una query di aggiornamento come mi sarei aspettato.

Invece, viene eseguita una query di inserimento:

INSERT INTO `Locales`(`id`, `locale`, `createdAt`, `updatedAt`, `visible`)
VALUES ('1', 'us', '2011-11-16 05:26:09', '2011-11-16 05:26:15', 1)

Quindi la mia domanda è: qual è il modo corretto per aggiornare un record utilizzando Sequelize ORM?

Risposte:


110

Non ho usato Sequelize , ma dopo aver letto la sua documentazione, è ovvio che stai istanziando un nuovo oggetto , ecco perché Sequelize inserisce un nuovo record nel db.

Per prima cosa devi cercare quel record, recuperarlo e solo dopo modificarne le proprietà e aggiornarlo , ad esempio:

Project.find({ where: { title: 'aProject' } })
  .on('success', function (project) {
    // Check if record exists in db
    if (project) {
      project.update({
        title: 'a very different title now'
      })
      .success(function () {})
    }
  })

Funziona, tuttavia ho dovuto cambiare .successin.then
Adam F

1
Dovrebbe essere Project.findOne(?
JBaczuk

2
Vecchia domanda ma pertinente se si cerca oggi (come ho fatto io). A partire da Sequelize 5, il modo corretto per trovare il record è con findByPk(req.params.id)quale restituisce un'istanza.
cstrutton

2
Questo non dovrebbe essere raccomandato, invia 2 query dove potrebbe essere fatto con una singola query. Si prega di controllare altre risposte di seguito.
Tᴀʀᴇǫ Mᴀʜᴍᴏᴏᴅ

219

A partire dalla versione 2.0.0 è necessario per avvolgere la cui clausola di un whereimmobile:

Project.update(
  { title: 'a very different title now' },
  { where: { _id: 1 } }
)
  .success(result =>
    handleResult(result)
  )
  .error(err =>
    handleError(err)
  )

Aggiornamento 2016-03-09

L'ultima versione in realtà non usa successe errorpiù ma usa invece thenpromesse -able.

Quindi il codice superiore apparirà come segue:

Project.update(
  { title: 'a very different title now' },
  { where: { _id: 1 } }
)
  .then(result =>
    handleResult(result)
  )
  .catch(err =>
    handleError(err)
  )

Utilizzo di async / await

try {
  const result = await Project.update(
    { title: 'a very different title now' },
    { where: { _id: 1 } }
  )
  handleResult(result)
} catch (err) {
  handleError(err)
}

http://docs.sequelizejs.com/en/latest/api/model/#updatevalues-options-promisearrayaffectedcount-affectedrows



Hai più voti positivi rispetto alla prima risposta del thread, penso che dovrebbe essere spostato alla prima risposta di questo thread di risposte. Saluti.
aananddham

37

Da sequelize v1.7.0 ora puoi chiamare un metodo update () sul modello. Molto più pulito

Per esempio:

Project.update(

  // Set Attribute values 
        { title:'a very different title now' },

  // Where clause / criteria 
         { _id : 1 }     

 ).success(function() { 

     console.log("Project with id =1 updated successfully!");

 }).error(function(err) { 

     console.log("Project update failed !");
     //handle error here

 });

eseguirà anche questa convalida?
Marconi

Da quello che ho letto nei documenti dell'API questo è il metodo preferito.
Michael J. Calkins,

4
In realtà è stato deprecato. Vedi il riferimento API ufficiale per Model .
Domi

Ecco i documenti al momento di questo commento: sono stati spostati in ReadTheDocs.
Chris Krycho

1
Come accennato, questa notazione è deprecata dalla 2.0.0. Fare riferimento anche a questa risposta: stackoverflow.com/a/26303473/831499
Matthias Dietrich

22

E per le persone che cercano una risposta a dicembre 2018, questa è la sintassi corretta usando le promesse:

Project.update(
    // Values to update
    {
        title:  'a very different title now'
    },
    { // Clause
        where: 
        {
            id: 1
        }
    }
).then(count => {
    console.log('Rows updated ' + count);
});

2
Questa dovrebbe essere la risposta migliore.
decoder7283

Non funziona nel 2019: errore di rifiuto non gestito: valore non valido [funzione]
neve

13

Risposta di gennaio 2020
La cosa da capire è che esiste un metodo di aggiornamento per il modello e un metodo di aggiornamento separato per un'istanza (record). Model.update()aggiorna TUTTI i record corrispondenti e restituisce un array vedere la documentazione di Sequelize . Instance.update()aggiorna il record e restituisce un oggetto istanza.

Quindi, per aggiornare un singolo record per la domanda, il codice sarebbe simile a questo:

SequlizeModel.findOne({where: {id: 'some-id'}})
.then(record => {
  
  if (!record) {
    throw new Error('No record found')
  }

  console.log(`retrieved record ${JSON.stringify(record,null,2)}`) 

  let values = {
    registered : true,
    email: 'some@email.com',
    name: 'Joe Blogs'
  }
  
  record.update(values).then( updatedRecord => {
    console.log(`updated record ${JSON.stringify(updatedRecord,null,2)}`)
    // login into your DB and confirm update
  })

})
.catch((error) => {
  // do seomthing with the error
  throw new Error(error)
})

Quindi, usa Model.findOne()o Model.findByPkId()per ottenere un handle di una singola istanza (record) e quindi usa ilInstance.update()


12

Penso che usare UPDATE ... WHEREcome spiegato qui e qui sia un approccio snello

Project.update(
      { title: 'a very different title no' } /* set attributes' value */, 
      { where: { _id : 1 }} /* where criteria */
).then(function(affectedRows) {
Project.findAll().then(function(Projects) {
     console.log(Projects) 
})

1
Questa potrebbe essere la risposta accettata. In questo modo puoi impostare solo alcuni campi e puoi specificare i criteri. Grazie mille :)
Luis Cabrera Benito

5

Questa soluzione è deprecata

failure | fail | error () è deprecato e verrà rimosso nella 2.1, si prega di utilizzare invece lo stile delle promesse.

quindi devi usare

Project.update(

    // Set Attribute values 
    {
        title: 'a very different title now'
    },

    // Where clause / criteria 
    {
        _id: 1
    }

).then(function() {

    console.log("Project with id =1 updated successfully!");

}).catch(function(e) {
    console.log("Project update failed !");
})

Ed è possibile utilizzare .complete()pure

Saluti


2

Utilizzo di async e await in un moderno javascript Es6

const title = "title goes here";
const id = 1;

    try{
    const result = await Project.update(
          { title },
          { where: { id } }
        )
    }.catch(err => console.log(err));

puoi restituire il risultato ...



1

È possibile utilizzare il metodo Model.update ().

Con async / await:

try{
  const result = await Project.update(
    { title: "Updated Title" }, //what going to be updated
    { where: { id: 1 }} // where clause
  )  
} catch (error) {
  // error handling
}

Con .then (). Catch ():

Project.update(
    { title: "Updated Title" }, //what going to be updated
    { where: { id: 1 }} // where clause
)
.then(result => {
  // code with result
})
.catch(error => {
  // error handling
})

1

ciao per aggiornare il record è molto semplice

  1. sequelize trova il record per ID (o da quello che vuoi)
  2. poi passi i parametri con result.feild = updatedField
  3. se il record non esiste nel database sequelize crea un nuovo record con i parametri
  4. guarda l'esempio per capire meglio il codice # 1 prova quel codice per tutte le versioni sotto V4
const sequelizeModel = require("../models/sequelizeModel");
    const id = req.params.id;
            sequelizeModel.findAll(id)
            .then((result)=>{
                result.name = updatedName;
                result.lastname = updatedLastname;
                result.price = updatedPrice;
                result.tele = updatedTele;
                return result.save()
            })
            .then((result)=>{
                    console.log("the data was Updated");
                })
            .catch((err)=>{
                console.log("Error : ",err)
            });

Codice per V5

const id = req.params.id;
            const name = req.body.name;
            const lastname = req.body.lastname;
            const tele = req.body.tele;
            const price = req.body.price;
    StudentWork.update(
        {
            name        : name,
            lastname    : lastname,
            tele        : tele,
            price       : price
        },
        {returning: true, where: {id: id} }
      )
            .then((result)=>{
                console.log("data was Updated");
                res.redirect('/');
            })
    .catch((err)=>{
        console.log("Error : ",err)
    });


0

Ci sono due modi per aggiornare il record in sequenza.

Innanzitutto, se si dispone di un identificatore univoco, è possibile utilizzare la clausola where oppure se si desidera aggiornare più record con lo stesso identificatore.

È possibile creare l'intero oggetto da aggiornare o una colonna specifica

const objectToUpdate = {
title: 'Hello World',
description: 'Hello World'
}

models.Locale.update(objectToUpdate, { where: { id: 2}})

Aggiorna solo una colonna specifica

models.Locale.update({ title: 'Hello World'}, { where: { id: 2}})

In secondo luogo, è possibile utilizzare trova una query per trovarla e utilizzare la funzione di impostazione e salvataggio per aggiornare il DB.


const objectToUpdate = {
title: 'Hello World',
description: 'Hello World'
}

models.Locale.findAll({ where: { title: 'Hello World'}}).then((result) => {
   if(result){
   // Result is array because we have used findAll. We can use findOne as well if you want one row and update that.
        result[0].set(objectToUpdate);
        result[0].save(); // This is a promise
}
})

Usa sempre la transazione durante l'aggiornamento o la creazione di una nuova riga. in questo modo ripristinerà eventuali aggiornamenti in caso di errori o se si eseguono più aggiornamenti:


models.sequelize.transaction((tx) => {
    models.Locale.update(objectToUpdate, { transaction: t, where: {id: 2}});
})
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.