Comment mettre à jour un enregistrement en utilisant sequelize pour node?

117

Je crée une API RESTful avec NodeJS, express, express-resource et Sequelize qui est utilisée pour gérer les ensembles de données stockés dans une base de données MySQL.

J'essaie de comprendre comment mettre à jour correctement un enregistrement à l'aide de Sequelize.

Je crée un modèle:

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

Ensuite, dans mon contrôleur de ressources, je définis une action de mise à jour.

Ici, je veux être en mesure de mettre à jour l'enregistrement où l'id correspond à une req.paramsvariable.

Je construis d'abord un modèle, puis j'utilise la updateAttributesméthode pour mettre à jour l'enregistrement.

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')
}

Maintenant, cela ne produit pas réellement une requête de mise à jour comme je m'y attendais.

Au lieu de cela, une requête d'insertion est exécutée:

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

Ma question est donc la suivante: quelle est la bonne façon de mettre à jour un enregistrement à l'aide de Sequelize ORM?

a_arias
la source

Réponses:

110

Je n'ai pas utilisé Sequelize , mais après avoir lu sa documentation, il est évident que vous instanciez un nouvel objet , c'est pourquoi Sequelize insère un nouvel enregistrement dans la base de données.

Vous devez d'abord rechercher cet enregistrement, le récupérer et seulement après cela, modifier ses propriétés et le mettre à jour , par exemple:

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 () {})
    }
  })
alessioalex
la source
Cela fonctionne, mais j'ai dû changer .successpour.then
Adam F
1
Doit-il l'être Project.findOne(?
JBaczuk
2
Ancienne question mais pertinente si vous cherchez aujourd'hui (comme je l'ai fait). Depuis Sequelize 5, la manière correcte de trouver l'enregistrement est de savoir avec findByPk(req.params.id)qui renvoie une instance.
cstrutton
2
Cela ne devrait pas être recommandé, il envoie 2 requêtes là où cela pourrait être fait par une seule requête. Veuillez vérifier les autres réponses ci-dessous.
Tᴀʀᴇǫ Mᴀʜᴍᴏᴏᴅ
219

Depuis la version 2.0.0, vous devez encapsuler votre clause where dans une wherepropriété:

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

Mise à jour 09/03/2016

La dernière version n'utilise en fait plus successet errorutilise à la place des thenpromesses utilisables.

Ainsi, le code supérieur ressemblera à ceci:

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

Utiliser 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

kube
la source
3
Les documents ont été déplacés vers: sequelize.readthedocs.org/en/latest/api/model/…
topher le
Vous avez plus de votes positifs que la première réponse de fil, je pense qu'il devrait être déplacé vers la première réponse de ce fil de réponses. À votre santé.
aananddham le
37

Depuis sequelize v1.7.0, vous pouvez désormais appeler une méthode update () sur le modèle. Beaucoup plus propre

Par exemple:

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

 });
Ferme
la source
est-ce que cette validation exécutera aussi?
Marconi
D'après ce que j'ai lu dans la documentation de l'API, c'est la méthode préférée.
Michael
4
Il est en fait obsolète. Consultez la référence officielle de l'API pour Model .
Domi
Voici les documents au moment de ce commentaire - ils ont été déplacés vers ReadTheDocs.
Chris Krycho
1
Comme mentionné, cette notation est obsolète depuis la version 2.0.0. Veuillez également vous référer à cette réponse: stackoverflow.com/a/26303473/831499
Matthias Dietrich
22

Et pour les personnes à la recherche d'une réponse en décembre 2018, voici la syntaxe correcte utilisant les promesses:

Project.update(
    // Values to update
    {
        title:  'a very different title now'
    },
    { // Clause
        where: 
        {
            id: 1
        }
    }
).then(count => {
    console.log('Rows updated ' + count);
});
Donkey Kong
la source
2
Cela devrait être la meilleure réponse.
decoder7283
Ne fonctionne pas en 2019: Erreur de rejet non gérée: valeur non valide [Fonction]
neige
13

Réponse de janvier 2020
Ce qu'il faut comprendre, c'est qu'il existe une méthode de mise à jour pour le modèle et une méthode de mise à jour distincte pour une instance (enregistrement). Model.update()met à jour TOUS les enregistrements correspondants et renvoie un tableau voir la documentation Sequelize . Instance.update()met à jour l'enregistrement et renvoie un objet d'instance.

Donc, pour mettre à jour un seul enregistrement par question, le code ressemblerait à ceci:

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: '[email protected]',
    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)
})

Donc, utilisez Model.findOne()ou Model.findByPkId()pour obtenir un handle une seule instance (enregistrement), puis utilisez leInstance.update()

RireBubba
la source
12

Je pense UPDATE ... WHEREqu'en utilisant comme expliqué ici et voici une approche lean

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) 
})
Hasan A Yousef
la source
1
Cela pourrait être la réponse acceptée. De cette façon, vous ne pouvez définir que certains champs et vous pouvez spécifier les critères. Merci beaucoup :)
Luis Cabrera Benito
5

Cette solution est obsolète

failure | fail | error () est obsolète et sera supprimé dans la version 2.1, veuillez utiliser plutôt le style promise.

donc vous devez utiliser

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 !");
})

Et vous pouvez utiliser .complete()aussi bien

Cordialement

Hussam
la source
2

Utiliser async et await dans un javascript Es6 moderne

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

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

vous pouvez renvoyer le résultat ...

Frank HN
la source
1

Vous pouvez utiliser la méthode Model.update ().

Avec 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
}

Avec .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
})
Leandro Lima
la source
1

salut pour mettre à jour l'enregistrement c'est très simple

  1. sequelize trouver l'enregistrement par ID (ou par ce que vous voulez)
  2. puis vous passez les paramètres avec result.feild = updatedField
  3. si l'enregistrement nexiste pas dans la base de données sequelize créer un nouvel enregistrement avec les paramètres
  4. regardez l'exemple pour plus comprendre Code # 1 testez ce code pour toutes les versions sous 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)
            });

Code pour 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)
    });
bahri noredine
la source
0

Il existe deux façons de mettre à jour l'enregistrement dans sequelize.

Tout d'abord, si vous avez un identifiant unique, vous pouvez utiliser la clause where ou bien si vous souhaitez mettre à jour plusieurs enregistrements avec le même identifiant.

Vous pouvez soit créer l'objet entier à mettre à jour, soit une colonne spécifique

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

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

Mettre à jour uniquement une colonne spécifique

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

Deuxièmement, vous pouvez utiliser rechercher une requête pour la trouver et utiliser la fonction set and save pour mettre à jour le 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
}
})

Utilisez toujours la transaction lors de la mise à jour ou de la création d'une nouvelle ligne. de cette façon, il annulera toutes les mises à jour s'il y a une erreur ou si vous effectuez plusieurs mises à jour:


models.sequelize.transaction((tx) => {
    models.Locale.update(objectToUpdate, { transaction: t, where: {id: 2}});
})
Siddharth Sunchu
la source