续集如何运作?

时间:2017-10-03 12:17:11

标签: node.js sequelize.js

我试图理解sequelize如何在一个简单的例子中起作用:用户可以有很多帖子,帖子只能有一个用户。

第一个问题,我不知道是否必须使用迁移或带同步的模型来创建我的数据库。我的意思是,我必须在两者中加入相同的代码。这是用户表的迁移:

module.exports = {
    up: (queryInterface, Sequelize) => {
        return queryInterface.createTable('Users', {
            id: {
                allowNull: false,
                autoIncrement: true,
                primaryKey: true,
                type: Sequelize.INTEGER
            },
            username: {
                allowNull: false,
                type: Sequelize.STRING,
                unique: true
            },
            password: {
                allowNull: false,
                type: Sequelize.STRING
            },
            email: {
                allowNull: false,
                type: Sequelize.STRING,
                unique: true
            },
            createdAt: {
                allowNull: false,
                type: Sequelize.DATE
            },
            updatedAt: {
                allowNull: false,
                type: Sequelize.DATE
            }
        });
    },
    down: (queryInterface, Sequelize) => {
        return queryInterface.dropTable('Users');
    }
};

这是Post模型:

'use strict';
module.exports = (sequelize, DataTypes) => {
    const User = sequelize.define('User', {
        username: DataTypes.STRING,
        password: DataTypes.STRING,
        email: DataTypes.STRING
    }, {
        classMethods: {
            associate: (models) => {
                User.hasMany(models.Post);
            }
        }
    });
    return User;
};

我是否还必须指定用户名,电子邮件不能为空且在模型中必须是唯一的?

我该如何添加外键?在一个教程中,他们告诉我数据库自动添加外键但是如果我使用迁移,我认为它不起作用,我必须设置它吗?

3 个答案:

答案 0 :(得分:2)

你是对的,你必须手动设置外键关系。

以下是官方文档链接:http://docs.sequelizejs.com/manual/tutorial/associations.html

您可以尝试以下代码:

var user_object = require('your_file_path');
var post_object = require('your_file_path');

user_object.hasMany(post_object, {
    foreignKey: 'user_id',
    sourceKey: 'user_id',
    onDelete: 'cascade',
    as:'Posts',
});

post_object.belongsTo(user_object, {
    foreignKey: 'user_id',
    sourceKey: 'user_id',
    onDelete: 'cascade',
    as:'Posts',
});

答案 1 :(得分:2)

对于您的版本“sequelize”:“^ 4.13.2”

删除了classMethods和instanceMethods。

一个:

const Model = sequelize.define('Model', {
    ...
}, {
    classMethods: {
        associate: function (model) {...}
    },
    instanceMethods: {
        someMethod: function () { ...}
    }
});

新:

const Model = sequelize.define('Model', {
    ...
});

// Class Method
Model.associate = function (models) {
    ...associate the models
};

// Instance Method
Model.prototype.someMethod = function () {..}

请参阅官方文档Upgrade to V4

因此,对于关系,你应该完成这个步骤:

  1. 导入模型
  2. 调用类“关联”方法(如果存在)
  3. 导出
  4. 示例:

    // models/index.js
    import fs from 'fs';
    import path from 'path';
    import Sequelize from 'sequelize';
    import config from './config';
    
    const sequelize = new Sequelize(config.db.url, config.db.options);
    
    const DB = {};
    
    // Import models
    fs
      .readdirSync(__dirname)
      .filter(file => (file.indexOf('.') !== 0) && (file !== path.basename(__filename)) && (file.slice(-3) === '.js'))
      .forEach((file) => {
        const model = sequelize.import(path.join(__dirname, file));
        DB[model.name] = model;
      });
    
    // Here u should call class method for associations
    Object.keys(DB).forEach((modelName) => {
      if ('associate' in DB[modelName]) {
        DB[modelName].associate(DB);
      }
    });
    
    DB.sequelize = sequelize;
    DB.Sequelize = Sequelize;
    
    export default DB;
    

    您可以将所有关系放入模型中。

    用户:

    // models/user.js
    export default (sequelize, DataTypes) => {
      const User = sequelize.define(
        'users',
        // Fields
        {
          id: {
            type: DataTypes.INTEGER,
            primaryKey: true,
            autoIncrement: true,
          },
          // etc ...
        },
        // Options
        {
          timestamps: false, // <-- turn off timestamps
          underscored: true, // <-- this option for naming with underscore. example: createdAt -> created_at
          validate: {},
          indexes: [],
        },
      );
    
      User.associate = (models) => {
        User.hasMany(models.post, { 
          // ... 
        });
        User.hasMany(models.comment, { 
          // ... 
        });
        // OR
        models.user.hasMany(models.post, {
          // ...
        });
      };
    
      return User;
    };
    

    发布:

    // models/post.js
    export default (sequelize, DataTypes) => {
      const Post = sequelize.define(
        'posts',
        // Fields
        {
          // ...
        },
        // Options
        {
          // ...
        },
      );
    
      Post.associate = (models) => {
        Post.belongsTo(models.user, { 
          // ... 
        });
        // OR
        models.post.belongsTo(models.user, {
          // ...
        });
      };
    
      return Post;
    };
    
      

    我是否还必须指定用户名,电子邮件不能为空   在模型中必须是唯一的吗?

    是的,您应该定义模型中的所有内容,例如键,关系等等。因为您的应用程序使用模型来执行数据库操作。

      

    我该如何添加外键?在一个教程中,他们说   我,数据库自动添加外键但我不认为   如果我使用迁移它是有效的,我必须设置它manualy no?

    实际上,您无法在创建表和字段的迁移中定义复合键。

    迁移的最佳做法应该是这样的:

    1. 000000_create_users_table
    2. 000001_add_foreign_keys_to_users_table
    3. 000002_add_new_field_to_users_table
    4. 等...
    5. 所以你应该在迁移中手动添加所有内容。

      要在迁移中添加索引,您应该使用queryInterface.addIndex

      module.exports = {
        up: queryInterface => queryInterface.addIndex(
          'users',
          {
            unique: true,
            fields: ['username', 'email'],
      // if u want to rename u can use:
      //    name: 'whatever'
      // by convention default name will be: table_field1_fieldN
          },
        ),
      
        down: queryInterface => queryInterface.removeIndex(
          'users',
          'users_username_email', // <-- this name by convention, but u can rename it
        ),
      };
      

      对于“键”,您应该使用queryInterface.addConstraint

      主键

      queryInterface.addConstraint('Users', ['username'], {
         type: 'primary key',
         name: 'custom_primary_constraint_name'
      });
      

      外键

      queryInterface.addConstraint('Posts', ['username'], {
        type: 'FOREIGN KEY',
        name: 'custom_fkey_constraint_name',
        references: { //Required field
          table: 'target_table_name',
          field: 'target_column_name'
        },
        onDelete: 'cascade',
        onUpdate: 'cascade'
      });
      

      检查所有API References

答案 2 :(得分:1)

我真的只是重新构建你的代码。

//创建一个数据库配置文件

var Sequelize=require('sequelize');

var connection=new Sequelize('project','user','password',{
    dialect:'mysql',
    logging:false
});

connection.authenticate()
  .then(() => {    
    console.log("Connected to database");
  })
  .catch(err => {
    //console.error("Can't connect to database :(\n", err);
  });


module.exports={
    database:connection,
}

//您的用户架构文件

var database = require('your_file_path/DatabaseConnection').database;

var Sequelize = require('sequelize');

var Users = database.define('users', {

    username: {
        allowNull: false,
        type: Sequelize.STRING,
        unique: true
    },
    password: {
        allowNull: false,
        type: Sequelize.STRING
    },
    email: {
        allowNull: false,
        type: Sequelize.STRING,
        unique: true
    }
}, {
    underscored: true
},hooks: {
    beforeCreate: (user, option) => {
        users.password = encrypto.encryptEntity(user.password);
        //for automatic encryption of password
    },

}

);

  Users.sync();

    //id, updated_at , and modified_at will be maintained by default

    module.exports = {
        Users
    }

//你的帖子文件路径

var Posts = database.define('posts', {

    post_content: {
        allowNull: false,
        type: Sequelize.STRING,
        unique: true
    }
}, {
    underscored: true
});

//importing User
var Users = require('file_path')

Users.hasMany(Posts, {
    foreignKey: 'user_id',
    sourceKey: 'user_id',
    onDelete: 'cascade',
    as:'Posts',
});

Posts.belongsTo(Users, {
    foreignKey: 'user_id',
    sourceKey: 'user_id',
    onDelete: 'cascade',
    as:'Users',
}); 
// two way binding.
Posts.sync();

通过维护关系,您可以使用setter和getter方法轻松更新数据

Posts.setUsers(user_object);

//上面的代码会自动将user_id找到user_object

//对于您可以使用的选择查询:

Users.findOne({
    where:{
        id:user_id
    },
    include: [{
        model: Posts,
        attributes: ['post_content'],
        as: "Posts"
    }//this will bring every posts user has created
})

我认为上面的编码标准会让你的代码看起来更干净,对更大的项目更有帮助。

希望这有帮助。