Wie aktualisiere ich einen Datensatz mit Sequelize for Node?

115

Ich erstelle eine RESTful-API mit NodeJS, Express, Express-Resource und Sequelize, mit der in einer MySQL-Datenbank gespeicherte Datasets verwaltet werden.

Ich versuche herauszufinden, wie ein Datensatz mithilfe von Sequelize ordnungsgemäß aktualisiert werden kann.

Ich erstelle ein Modell:

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

Anschließend definiere ich in meinem Ressourcencontroller eine Aktualisierungsaktion.

Hier möchte ich in der Lage sein, den Datensatz zu aktualisieren, in dem die ID mit einer req.paramsVariablen übereinstimmt.

Zuerst erstelle ich ein Modell und verwende dann die updateAttributesMethode, um den Datensatz zu aktualisieren.

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

Dies führt nicht zu einer Aktualisierungsabfrage, wie ich es erwarten würde.

Stattdessen wird eine Einfügeabfrage ausgeführt:

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

Meine Frage lautet also: Wie kann ein Datensatz mit Sequelize ORM ordnungsgemäß aktualisiert werden?

a_arias
quelle

Antworten:

109

Ich habe Sequelize nicht verwendet , aber nach dem Lesen der Dokumentation ist es offensichtlich, dass Sie ein neues Objekt instanziieren. Deshalb fügt Sequelize einen neuen Datensatz in die Datenbank ein.

Zuerst müssen Sie nach diesem Datensatz suchen, ihn abrufen und erst danach seine Eigenschaften ändern und aktualisieren , zum Beispiel:

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
quelle
Dies funktioniert, aber ich musste .successzu.then
Adam F
1
Sollte es sein Project.findOne(?
JBaczuk
2
Alte Frage, aber relevant für die heutige Suche (wie ich). Ab Sequelize 5 ist der richtige Weg, um den Datensatz zu finden, der, mit findByPk(req.params.id)dem eine Instanz zurückgegeben wird.
Cstrutton
2
Dies sollte nicht empfohlen werden, es werden 2 Abfragen gesendet, bei denen dies durch eine einzelne Abfrage erfolgen kann. Bitte überprüfen Sie andere Antworten unten.
Tᴀʀᴇǫ Mᴀʜᴍᴏᴏᴅ
219

Seit Version 2.0.0 müssen Sie Ihre where- Klausel in eine whereEigenschaft einschließen:

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

Update 2016-03-09

Die neueste Version verwendet eigentlich nicht mehr successund errorverwendet stattdessen then-able Versprechen.

Der obere Code sieht also wie folgt aus:

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

Verwenden von 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/de/latest/api/model/#updatevalues-options-promisearrayaffectedcount-affectedrows

kube
quelle
3
Die Dokumente wurden
topher
Sie haben mehr positive Stimmen als die erste Thread-Antwort. Ich denke, sie sollte in die erste Antwort dieses Antwort-Threads verschoben werden. Prost.
Aananddham
37

Seit der Fortsetzung von Version 1.7.0 können Sie jetzt eine update () -Methode für das Modell aufrufen. Viel sauberer

Beispielsweise:

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

 });
Bauernhof
quelle
Wird dies auch eine Validierung durchführen?
Marconi
Nach dem, was ich in den API-Dokumenten gelesen habe, ist dies die bevorzugte Methode.
Michael J. Calkins
4
Es wurde tatsächlich veraltet. Siehe die offizielle API-Referenz für das Modell .
Domi
Hier sind die Dokumente zum Zeitpunkt dieses Kommentars - sie wurden zu ReadTheDocs verschoben.
Chris Krycho
1
Wie bereits erwähnt, ist diese Notation seit 2.0.0 veraltet. Bitte beziehen Sie sich auch auf diese Antwort: stackoverflow.com/a/26303473/831499
Matthias Dietrich
22

Und für Leute, die im Dezember 2018 nach einer Antwort suchen, ist dies die richtige Syntax mit Versprechungen:

Project.update(
    // Values to update
    {
        title:  'a very different title now'
    },
    { // Clause
        where: 
        {
            id: 1
        }
    }
).then(count => {
    console.log('Rows updated ' + count);
});
DonkeyKong
quelle
2
Dies sollte die beste Antwort sein.
decoder7283
2019 funktioniert nicht: Nicht behandelte Ablehnung Fehler: Ungültiger Wert [Funktion]
Schnee
13

Januar 2020 Antwort
Es ist zu verstehen, dass es eine Aktualisierungsmethode für das Modell und eine separate Aktualisierungsmethode für eine Instanz (Datensatz) gibt. Model.update()aktualisiert ALLE übereinstimmenden Datensätze und gibt ein Array zurück ( siehe Dokumentation zu Sequelize) . Instance.update()aktualisiert den Datensatz und gibt ein Instanzobjekt zurück.

Um also einen einzelnen Datensatz pro Frage zu aktualisieren, würde der Code ungefähr so ​​aussehen:

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

Verwenden Sie also Model.findOne()oder Model.findByPkId(), um eine einzelne Instanz (Datensatz) in den Griff zu bekommen, und verwenden Sie dann dieInstance.update()

LaughingBubba
quelle
11

Ich denke, UPDATE ... WHEREwie hier und hier erklärt zu verwenden, ist ein schlanker Ansatz

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
quelle
5

Diese Lösung ist veraltet

fail | fail | error () ist veraltet und wird in 2.1 entfernt. Verwenden Sie stattdessen den Versprechungsstil.

also musst du verwenden

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

Und Sie können verwendet werden .complete()als auch

Grüße

Hussam
quelle
2

Verwenden Sie Async und warten Sie in einem modernen Javascript Es6

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

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

Sie können Ergebnis zurückgeben ...

Frank HN
quelle
1

öffentliches statisches Update (Werte: Objekt, Optionen: Objekt): Versprechen>

Überprüfen Sie die Dokumentation einmal unter http://docs.sequelizejs.com/class/lib/model.js~Model.html#static-method-update

  Project.update(
    // Set Attribute values 
    { title:'a very different title now' },
  // Where clause / criteria 
     { _id : 1 }     
  ).then(function(result) { 

 //it returns an array as [affectedCount, affectedRows]

  })
Vijay Kumar
quelle
1

Sie können die Model.update () -Methode verwenden.

Mit async / warte:

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

Mit .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
quelle
1

Hallo, um den Datensatz zu aktualisieren, ist es sehr einfach

  1. Folgen Sie der Suche nach ID (oder nach Ihren Wünschen).
  2. dann übergeben Sie die Parameter mit result.feild = updatedField
  3. Wenn der Datensatz in der Datenbank-Folge nicht vorhanden ist, erstellen Sie einen neuen Datensatz mit den Parametern
  4. Sehen Sie sich das Beispiel an, um mehr zu verstehen. Code Nr. 1 Testen Sie diesen Code für alle Versionen unter 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 für 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
quelle
0

Es gibt zwei Möglichkeiten, wie Sie den Datensatz nacheinander aktualisieren können.

Wenn Sie einen eindeutigen Bezeichner haben, können Sie zunächst die where-Klausel verwenden oder mehrere Datensätze mit demselben Bezeichner aktualisieren.

Sie können entweder das gesamte zu aktualisierende Objekt oder eine bestimmte Spalte erstellen

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

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

Aktualisieren Sie nur eine bestimmte Spalte

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

Zweitens können Sie eine Abfrage suchen verwenden, um sie zu finden, und die Funktion set and save verwenden, um die Datenbank zu aktualisieren.


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

Verwenden Sie beim Aktualisieren oder Erstellen einer neuen Zeile immer die Transaktion. Auf diese Weise werden alle Updates zurückgesetzt, wenn ein Fehler auftritt oder wenn Sie mehrere Updates durchführen:


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