2016-05-14 69 views
0

我有一個記錄列表,我正在用單個表單字段中的調整值進行批量更新。當我嘗試運行POST並根據輸入值更新記錄時,我在Where子句中遇到了一個錯誤,我想知道如何解析where子句的discoverySourceId值或什麼是最好的方法來使用我當前的設置。Sequelize批量更新數組問題

Error: Missing where attribute in the options parameter passed to update. 

路線:

var appRoutes = express.Router(); 
var _ = require('lodash-node'); 
var async = require('async'); 
var models = require('../models/db-index'); 

    appRoutes.route('app/settings/discovery-sources') 

    .get(function(req, res){ 
     models.DiscoverySource.findAll({ 
       where: { 
        organizationId: req.user.organizationId 
       }, attributes: ['discoverySourceId', 'discoverySourceName'] 
      }).then(function(discoverySource){ 
      res.render('pages/app/settings-discovery-sources.hbs', { 
       discoverySource: discoverySource 
      }); 
     }) 
    }) 
     .post(function(req, res){ 
       console.log('POST Triggered'); 
       var sources = _.map(req.body.discoverySourceName, function (source) { 
        return { 
         discoverySourceName: source, 
         discoverySourceId: req.body.discoverySourceId 
        }; 
       }); 
       models.DiscoverySource.update(sources).then(function(){ 
        console.log("Successful update"); 
        res.redirect('/settings/discovery-sources'); 
       }); 
      }); 

**Form:** 

    <div class="row"> 
     <div class="col-md-8 col-md-offset-2"> 
      <div class="annotation-form"> 
       <h2>Discovery Sources</h2> 
       <form action="/app/settings/discovery-sources" method="post"> 
       {{#each discoverySource}} 
        <input type="hidden" name="discoverySourceId" value={{this.discoverySourceId}}> 
        <input type="text" name="discoverySourceName[0]" value="{{this.discoverySourceName}}"><a href="#" id="settings-delete-discovery-source">Delete</a> 
        <br /> 
       {{else}} 
        <p>No Discovery Sources</p> 
       {{/each}} 
        <button type="submit">Update Sources</button> 
       </form> 
      </div> 
     </div> 
    </div> 

discoverySource:

module.exports = function(sequelize, DataTypes) { 

var DiscoverySource = sequelize.define('discovery_source', { 
    discoverySourceId: { 
     type: DataTypes.INTEGER, 
     field: 'discovery_source_id', 
     autoIncrement: true, 
     primaryKey: true, 
     notNull: true, 
    }, 
    discoverySourceName: { 
     type: DataTypes.STRING, 
     field: 'discovery_source_name' 
    }, 
    organizationId: { 
     type: DataTypes.TEXT, 
     field: 'organization_id' 
    }, 
},{ 
    freezeTableName: true 
}); 
    return DiscoverySource; 
} 
+0

您錯過了更新調用中的where子句。將organizationId傳遞到where子句,否則它將更新DiscoverySource表中的每一行。 – grimurd

+0

我應該如何包含where子句?我試過'models.DiscoverySource.update(sources,{where:{discoverySourceId:req.body.discoverySourceId}})',但收到'未處理的拒絕TypeError:build.set不是函數的錯誤 – cphill

+0

我在這裏猜測,但req.body.discoverySourceId最有可能是一個字符串類型而不是數字類型(因爲隱藏的輸入被解析爲字符串,而不是數字)。嘗試parseInt(req.body.discoverySourceId) – grimurd

回答

3
var appRoutes = express.Router(); 
var _ = require('lodash-node'); // just use lodash, using lodash-node is deprecated and it's redundant. 
var async = require('async'); 
var models = require('../models/db-index'); 

// Added these for context 
var app = express(); 
var Promise = require('bluebird'); // or Q if you prefer. 

// Make sure you're using body-parser urlencoded 
// with extended set to true. This allows us to have 
// fancy body parsing for forms. 
// This line must be above all your routes. 
var bodyParser = require('body-parser'); 
app.use(bodyParser.urlencoded({ 
    extended: true 
})) 

appRoutes.route('app/settings/discovery-sources') 
    .get(function (req, res) { 
     models 
      .DiscoverySource 
      .findAll({ 
       where: { 
        organizationId: req.user.organizationId 
       }, 
       attributes: ['discoverySourceId', 'discoverySourceName'] 
      }) 
      .then(function (discoverySource) { 
       res.render('pages/app/settings-discovery-sources.hbs', { 
        discoverySource: discoverySource 
       }); 
      }) 
    }) 
    .post(function (req, res) { 
     console.log('POST Triggered'); 
     // We use promise.map to map the array in the body into an array of promises 
     // which are resolved when each promise has been resolved. 
     // It's a good idea here to use sequelize.transaction() so that if one update 
     // fails, everything gets rolled back. 
     // If you're using Q it doesn't support .map() so this looks slightly different in that case. 
     // q.all(_.map(req.body.discoverySources, function() {})) 
     Promise 
      .map(req.body.discoverySources, function (source) { 
       return models 
        .DiscoverySource 
        .update({ 
         discoverySourceName: source.name 
        }, { 
         // We have to call update with the ID of each discoverySource so that 
         // we update the names of each discovery source correctly. 
         where: { 
          discoverySourceId: source.id 
         } 
        }) 
      }) 
      .then(function() { 
       console.log("Successful update"); 
       res.redirect('/settings/discovery-sources'); 
      }); 
    }); 

HTML

<div class="row"> 
    <div class="col-md-8 col-md-offset-2"> 
     <div class="annotation-form"> 
      <h2>Discovery Sources</h2> 
      <form action="/app/settings/discovery-sources" method="post"> 
       {{#each discoverySource}} 
       <!-- Use body parser urlencoded syntax so the request body is parsed into an array of objects with the 
       properties id and name. See the qs library for syntax documentation, https://www.npmjs.com/package/qs#readme --> 
       <input type="hidden" name="discoverySources[][id]" value={{this.discoverySourceId}}> 
       <input type="text" name="discoverySources[][name]" value="{{this.discoverySourceName}}"><a href="#" id="settings-delete-discovery-source">Delete</a> 
       <br /> {{else}} 
       <p>No Discovery Sources</p> 
       {{/each}} 
       <button type="submit">Update Sources</button> 
      </form> 
     </div> 
    </div> 
</div> 
+0

感謝您的答案,它絕對是最好的方法,但我遇到了一個錯誤:'未處理的拒絕SequelizeValidationError:字符串違規:discoverySourceName不能是數組或對象。有關這個錯誤的任何想法?這是否基本上表明我需要循環路由端的'.update()'方法而不是將視圖中的元素傳遞給數組? – cphill

+0

沒有theres可能在我寫的HTML錯誤。做一個控制檯。登錄post路徑中的req.body並檢查它是否有正確設置了兩個屬性的對象數組。聽起來像discoverysourcename是一個數組出於某種原因。 – grimurd

+0

您使用的是什麼模板引擎?鬍子? – grimurd

0

我想補充的@GrimurD答案 - 如果更新,當你想回到更新的數據,你可以這樣做:

Promise 
    .all(_.map(clients, (client) => { 
     const { firstName, lastName, phoneNumber, emailAddress } = client; 
     return Client 
     .update({ 
      firstName, 
      lastName, 
      phoneNumber, 
      emailAddress, 
     }, { 
      where: { 
      id: client.id, 
      }, 
      returning: true, 
      plain: true, 
     }); 
    })) 
    .then((results) => { 
     // do whatever you want with the returned results 
     const updatedClients = results.map(result => _.omit(result[1].dataValues, ['salt', 'password'])); 
     callback(null, updatedClients); 
    }) 
    .catch((err) => { 
     callback({ error: true, message: err.message ? err.message : 'Unable to fetch updated user details' }); 
    }); 

因此,所有的更新記錄,將返回爲對象的數組和你可以做任何你想要的數據。