admin管理员组

文章数量:1434924

The sequelize documentation (/) states:

If you pass a model the returned data will be instances of that model.

// Callee is the model definition. This allows you to easily map a query to a predefined model
sequelize.query('SELECT * FROM projects', { model: Projects }).then(function(projects){
  // Each record will now be a instance of Project
})

I have defined a model for a resource called agent.

module.exports = function(sequelize, DataTypes) {
   let Agent = sequelize.define('Agent', {
      responseStatus: DataTypes.STRING,
      agentnum: {
        type: DataTypes.STRING,
        primaryKey: true,
        allowNull: false,
        field : 'agentno'
      },
      fname :  {
        type: DataTypes.STRING,
        allowNull : false,
        field: 'fname'
      },
      lname : {
        type: DataTypes.STRING,
        allowNull: false,
        field : 'lname'
      }, 
      fullname : {
        type: DataTypes.STRING,
        allowNull : false,
        field: 'full_name'
      }, 
      status : {
        type: DataTypes.STRING,
        allowNull: false,
        field: 'business_status'
      }, 
      loginDate: DataTypes.DATE
  }, {
      freezeTableName: false,
      timestamps: false
  });

  return Agent;
};

And when calling sequelize.query with my query and specifying model:Agent, I get an error thrown from sequelize:

TypeError: this.model.bulkBuild is not a function

the stack points to sequelize\lib\dialects\abstract\query.js:675.

This error persists until I apply a QueryType of sequelize.QueryTypes.RAW. At this point the query pletes and I get a JSON response but it is not an instance of my Agent model. The JSON response from the sequelize query contains field names that should be mapped to.

I have imported my model (its just one) according to the directions found in their express sample (.js). The models collection shows that my Agent model is included.

import Sequelize from 'sequelize';
import config from './config';

export default callback => {
  const sequelize = new Sequelize(config.database, config.username, config.password, config.params);

  sequelize.sync().then(function() {
    let db = { }

    let agentModel = sequelize.import('model/agent.js');
    db[agentModel.name] = agentModel;

    db.sequelize = sequelize;
    db.Sequelize = Sequelize;

    db.sequelize.authenticate().then(function() {
      console.log('CONNECTION OK');
    });


    callback(db);

  }).catch(function(err) {
    console.log('FAILED TO CONNECT: ', err.message);
  });
}

I want the query to return an instance of Agent when that query is run (invoked from a POST to my api). I am using MS SQL Server 2008 R2.

Any input is appreciated. Thanks.

EDIT 1/30 Here is the code generating the sequelize object, and passing in the model. The model collection shows my item is added, but it has no properties.

connectDb: (function () {
        var sequelize;
        function createInstance() {
            var sequelizeInstance, connectedAndAuthenticated;
            sequelizeInstance = new Sequelize(config.database, config.username, config.password, config.params);
            connectedAndAuthenticated = sequelizeInstance.authenticate();
            connectedAndAuthenticated.sequelize = sequelizeInstance;
            connectedAndAuthenticated.Sequelize = Sequelize;

            var model = sequelizeInstance.import('../src/model/agent.js');


            return connectedAndAuthenticated;
        }
        return {
            getInstance : function () {
                if (!sequelize) {
                    sequelize = createInstance();
                }
                return sequelize;
            }
        };
    }())

EDIT 1/26 After manipulating the QueryTypes, I discovered two things - that I inadvertently created a table in the database with the name of the model (Agent), and that the object returned has a tablename property value of empty. The schema and tablename are specified by me, but the query, being a stored procedure that joins a number of queries and tables, does not directly map to an object in my database named Agent. That being said, the documentation to me seems to suggest that this does not and should not matter, as I am creating my own model that is bound to the query result.

The sequelize documentation (http://docs.sequelizejs./en/v3/docs/raw-queries/) states:

If you pass a model the returned data will be instances of that model.

// Callee is the model definition. This allows you to easily map a query to a predefined model
sequelize.query('SELECT * FROM projects', { model: Projects }).then(function(projects){
  // Each record will now be a instance of Project
})

I have defined a model for a resource called agent.

module.exports = function(sequelize, DataTypes) {
   let Agent = sequelize.define('Agent', {
      responseStatus: DataTypes.STRING,
      agentnum: {
        type: DataTypes.STRING,
        primaryKey: true,
        allowNull: false,
        field : 'agentno'
      },
      fname :  {
        type: DataTypes.STRING,
        allowNull : false,
        field: 'fname'
      },
      lname : {
        type: DataTypes.STRING,
        allowNull: false,
        field : 'lname'
      }, 
      fullname : {
        type: DataTypes.STRING,
        allowNull : false,
        field: 'full_name'
      }, 
      status : {
        type: DataTypes.STRING,
        allowNull: false,
        field: 'business_status'
      }, 
      loginDate: DataTypes.DATE
  }, {
      freezeTableName: false,
      timestamps: false
  });

  return Agent;
};

And when calling sequelize.query with my query and specifying model:Agent, I get an error thrown from sequelize:

TypeError: this.model.bulkBuild is not a function

the stack points to sequelize\lib\dialects\abstract\query.js:675.

This error persists until I apply a QueryType of sequelize.QueryTypes.RAW. At this point the query pletes and I get a JSON response but it is not an instance of my Agent model. The JSON response from the sequelize query contains field names that should be mapped to.

I have imported my model (its just one) according to the directions found in their express sample (https://github./sequelize/express-example/blob/master/models/index.js). The models collection shows that my Agent model is included.

import Sequelize from 'sequelize';
import config from './config';

export default callback => {
  const sequelize = new Sequelize(config.database, config.username, config.password, config.params);

  sequelize.sync().then(function() {
    let db = { }

    let agentModel = sequelize.import('model/agent.js');
    db[agentModel.name] = agentModel;

    db.sequelize = sequelize;
    db.Sequelize = Sequelize;

    db.sequelize.authenticate().then(function() {
      console.log('CONNECTION OK');
    });


    callback(db);

  }).catch(function(err) {
    console.log('FAILED TO CONNECT: ', err.message);
  });
}

I want the query to return an instance of Agent when that query is run (invoked from a POST to my api). I am using MS SQL Server 2008 R2.

Any input is appreciated. Thanks.

EDIT 1/30 Here is the code generating the sequelize object, and passing in the model. The model collection shows my item is added, but it has no properties.

connectDb: (function () {
        var sequelize;
        function createInstance() {
            var sequelizeInstance, connectedAndAuthenticated;
            sequelizeInstance = new Sequelize(config.database, config.username, config.password, config.params);
            connectedAndAuthenticated = sequelizeInstance.authenticate();
            connectedAndAuthenticated.sequelize = sequelizeInstance;
            connectedAndAuthenticated.Sequelize = Sequelize;

            var model = sequelizeInstance.import('../src/model/agent.js');


            return connectedAndAuthenticated;
        }
        return {
            getInstance : function () {
                if (!sequelize) {
                    sequelize = createInstance();
                }
                return sequelize;
            }
        };
    }())

EDIT 1/26 After manipulating the QueryTypes, I discovered two things - that I inadvertently created a table in the database with the name of the model (Agent), and that the object returned has a tablename property value of empty. The schema and tablename are specified by me, but the query, being a stored procedure that joins a number of queries and tables, does not directly map to an object in my database named Agent. That being said, the documentation to me seems to suggest that this does not and should not matter, as I am creating my own model that is bound to the query result.

Share Improve this question edited Jan 30, 2017 at 15:29 Elliot Rodriguez asked Jan 24, 2017 at 18:28 Elliot RodriguezElliot Rodriguez 6181 gold badge7 silver badges26 bronze badges 4
  • what is your query? – Adam Commented Jan 24, 2017 at 20:06
  • db.sequelize .query( "DECLARE @response VARCHAR(256); EXEC API_Login @agentnum = N'" + agentNum + "', @hashedPassword = '" + password + "', @response = @response OUTPUT; SELECT @response AS N'response'",{ model: Agent, type: sequelize.QueryTypes.RAW}) .spread(function(Agent) { res.status(200).json(Agent); }) .catch(function(err) { handleError(err, res); }); - It's a stored procedure being invoked. – Elliot Rodriguez Commented Jan 24, 2017 at 20:10
  • what if you do type: sequelize.QueryTypes.SELECT ? – Adam Commented Jan 24, 2017 at 20:14
  • @Adam every other QueryType either fails or returns nothing in the response. – Elliot Rodriguez Commented Jan 24, 2017 at 20:17
Add a ment  | 

2 Answers 2

Reset to default 2

sequelize doc is confusing .i'm explaining you clean way to use sequelize put

var models = require('../models');

in your code file be sure models directory contain index.js as you told me in your question and also Project model. be careful, other then correctly configured model there must not anything. Now put

 models.sequelize.query("select 1 as val").then(function(result){
console.log(result)
})

in your code to check connection also you should use find query like

 models.Projects.findAll().then(function(result){
    console.log(result)
    })

It seems like a simple typo. I don't think Agent is actually defined in your scope. I think you should be passing agentModel or whatever you bound the import to.

let agentModel = sequelize.import('model/agent.js');    
db.sequelize.query( "DECLARE @response VARCHAR(256); EXEC API_Login @agentnum = N'" + agentNum + "', @hashedPassword = '" + password + "', @response = @response OUTPUT; SELECT @response AS N'response'",{ model: agentModel, type: sequelize.QueryTypes.RAW}) .spread(function(Agent) { res.status(200).json(Agent); }) .catch(function(err) { handleError(err, res); });

Note I'm using {model: agentModel, ...} not {model: Agent, ...} because Agent is undefined outside of the callback.

Your error TypeError: this.model.bulkBuild is not a function makes perfect sense if Agent is not actually a model but something else (or undefined).

UPDATE

You mention in ments on the post below that: "I have synced the model - the query attempts to create a table, instead of binding to the passed in agent model" and "It should not be creating a table".

Why do you think that is that is the case? Creating the table during sync() is normal behaviour for Sequelize.

I think you misunderstand how Sequelize works. It creates a table for every registered model during sync. If it can't create that table it might be returning an invalid model and that is why you are getting errors.

Models are explicity tied to individual database tables, that's the fundamental behavior of Sequelize. Each model instance represents a row of that table. If you are working with stored proceedures then you are probably better off using using the native database library and defining your own abstraction layer.

I'm sure you can disable and/or override all the default synchronization between the model and the underlying DB table but at a certain point or plexity you'd have basically just written your own abstraction library and it would be cleaner to just do it from scratch.

Maybe you can use Sequelize the way you want but at the very least you should not be calling sync(). What side-effects that leads to I can't say but I can say that unless you define your own beforeSync hook sync() will always create a table in your schema:

Model.prototype.sync = function(options) {
  options = options || {};
  options.hooks = options.hooks === undefined ? true : !!options.hooks;
  options = Utils._.extend({}, this.options, options);

  var self = this
    , attributes = this.tableAttributes;

  return Promise.try(function () {
    if (options.hooks) {
      return self.runHooks('beforeSync', options);
    }
  }).then(function () {
    if (options.force) {
      return self.drop(options);
    }
  }).then(function () {
    return self.QueryInterface.createTable(self.getTableName(options), attributes, options, self);
  })
  ...
  }).return(this);
};

本文标签: javascriptSequelize not returning instance of modelStack Overflow