【问题标题】:'as' must be defined for many-to-many self-associations error whenever I try to create many-to-many association between 2 models每当我尝试在 2 个模型之间创建多对多关联时,必须为多对多自关联错误定义“as”
【发布时间】:2020-07-21 16:42:09
【问题描述】:

我正在关注 Sequelize 关于如何创建多对多关系的文档,但是,我不断收到此错误:

'as' must be defined for many-to-many self-associations

即使我正在关注此文档 - https://sequelize.org/master/manual/advanced-many-to-many.html

我有 2 个模型,用户和服务器,我尝试这样定义关系:

let User = require('./models/User');
let Server = require('./models/User');

User.belongsToMany(Server, { through: 'Server_User' });
Server.belongsToMany(User, { through: 'Server_User' });

但我收到以下错误:'as' must be defined for many-to-many self-associations

用户:

let Sequelize = require('sequelize');
let sequelize = require('../controllers/DatabaseController');

let User = sequelize.define('user', {
    id: {
        primaryKey: true,
        type: Sequelize.INTEGER,
        autoIncrement: true,
        allowNull: false,
    },
    username: {
        type: Sequelize.STRING,
        allowNull: false,
    },
    password: {
        type: Sequelize.STRING,
        allowNull: false,
    },
    email: {
        type: Sequelize.STRING,
        allowNull: false,
    }
})

module.exports = User;

服务器:

let Sequelize = require('sequelize');
let sequelize = require('../controllers/DatabaseController');

let Server = sequelize.define('server', {
    id: {
        primaryKey: true,
        type: Sequelize.INTEGER,
        autoIncrement: true,
        allowNull: false,
    },
    user_id: {
        type: Sequelize.INTEGER,
        allowNull: false,
    },
    name: {
        type: Sequelize.STRING,
        allowNull: false
    },
    thumbnail: {
        type: Sequelize.STRING(1400),
        allowNull: false,
    },
    endpoint: {
        type: Sequelize.UUID,
        defaultValue: Sequelize.UUIDV4,
        allowNull: false,
    },
    rooms: {
        type: Sequelize.JSON,
        allowNull: false,
        defaultValue: [{ name: 'General', history: []}]
    }
})

module.exports = Server;

【问题讨论】:

    标签: node.js sequelize.js


    【解决方案1】:

    它适用于"sequelize": "^5.21.3"。该错误可能是由其他代码引起的。这是一个完整的工作示例:

    ./models/User.ts:

    import { sequelize } from '../../../db';
    import Sequelize from 'sequelize';
    
    let User = sequelize.define('user', {
      id: {
        primaryKey: true,
        type: Sequelize.INTEGER,
        autoIncrement: true,
        allowNull: false,
      },
      username: {
        type: Sequelize.STRING,
        allowNull: false,
      },
      password: {
        type: Sequelize.STRING,
        allowNull: false,
      },
      email: {
        type: Sequelize.STRING,
        allowNull: false,
      },
    });
    
    export default User;
    

    ./models/Server.ts:

    import { sequelize } from '../../../db';
    import Sequelize from 'sequelize';
    
    let Server = sequelize.define('server', {
      id: {
        primaryKey: true,
        type: Sequelize.INTEGER,
        autoIncrement: true,
        allowNull: false,
      },
      user_id: {
        type: Sequelize.INTEGER,
        allowNull: false,
      },
      name: {
        type: Sequelize.STRING,
        allowNull: false,
      },
      thumbnail: {
        type: Sequelize.STRING(1400),
        allowNull: false,
      },
      endpoint: {
        type: Sequelize.UUID,
        defaultValue: Sequelize.UUIDV4,
        allowNull: false,
      },
      rooms: {
        type: Sequelize.JSON,
        allowNull: false,
        defaultValue: [{ name: 'General', history: [] }],
      },
    });
    
    export default Server;
    

    ./models/index.ts:

    import User from './User';
    import Server from './Server';
    
    (User as any).belongsToMany(Server, { through: 'Server_User' });
    (Server as any).belongsToMany(User, { through: 'Server_User' });
    
    export { User, Server };
    

    index.ts:

    import { User, Server } from './models';
    import { sequelize } from '../../db';
    import faker from 'faker';
    
    (async function test() {
      try {
        await sequelize.sync({ force: true });
        await (User as any).bulkCreate(
          [
            {
              id: 1,
              username: faker.name.findName(),
              password: faker.internet.password(),
              email: faker.internet.email(),
              servers: [
                { user_id: 1, name: faker.name.findName(), thumbnail: faker.random.image(), endpoint: faker.random.uuid() },
                { user_id: 1, name: faker.name.findName(), thumbnail: faker.random.image(), endpoint: faker.random.uuid() },
              ],
            },
            {
              id: 2,
              username: faker.name.findName(),
              password: faker.internet.password(),
              email: faker.internet.email(),
              servers: [
                { user_id: 2, name: faker.name.findName(), thumbnail: faker.random.image(), endpoint: faker.random.uuid() },
              ],
            },
          ],
          { include: [Server] },
        );
      } catch (error) {
        console.log(error);
      } finally {
        await sequelize.close();
      }
    })();
    

    测试函数的执行结果:

    Executing (default): DROP TABLE IF EXISTS "Server_User" CASCADE;
    Executing (default): DROP TABLE IF EXISTS "server" CASCADE;
    Executing (default): DROP TABLE IF EXISTS "user" CASCADE;
    Executing (default): DROP TABLE IF EXISTS "user" CASCADE;
    Executing (default): CREATE TABLE IF NOT EXISTS "user" ("id"   SERIAL , "username" VARCHAR(255) NOT NULL, "password" VARCHAR(255) NOT NULL, "email" VARCHAR(255) NOT NULL, PRIMARY KEY ("id"));
    Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'user' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
    Executing (default): DROP TABLE IF EXISTS "server" CASCADE;
    Executing (default): CREATE TABLE IF NOT EXISTS "server" ("id"   SERIAL , "user_id" INTEGER NOT NULL, "name" VARCHAR(255) NOT NULL, "thumbnail" VARCHAR(1400) NOT NULL, "endpoint" UUID NOT NULL, "rooms" JSON NOT NULL DEFAULT '[{"name":"General","history":[]}]', PRIMARY KEY ("id"));
    Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'server' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
    Executing (default): DROP TABLE IF EXISTS "Server_User" CASCADE;
    Executing (default): CREATE TABLE IF NOT EXISTS "Server_User" ("userId" INTEGER  REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE CASCADE, "serverId" INTEGER  REFERENCES "server" ("id") ON DELETE CASCADE ON UPDATE CASCADE, PRIMARY KEY ("userId","serverId"));
    Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'Server_User' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
    Executing (default): INSERT INTO "user" ("id","username","password","email") VALUES (1,'Kayley O''Reilly Jr.','jbXGDr5PHon4XH4','Elissa_MacGyver@gmail.com'),(2,'Daisha Kohler PhD','mAQ1ttIF1LcQ8mq','Albin_Weimann30@yahoo.com') RETURNING *;
    Executing (default): INSERT INTO "server" ("id","user_id","name","thumbnail","endpoint","rooms") VALUES (DEFAULT,1,'Ms. Denis Kilback','http://lorempixel.com/640/480/food','e7bff975-abcd-4b86-8af2-024557bdd5d4','[{"name":"General","history":[]}]'),(DEFAULT,1,'Everardo Anderson','http://lorempixel.com/640/480/technics','79ad1819-cb64-4846-8aea-ff4a5fdce1fb','[{"name":"General","history":[]}]'),(DEFAULT,2,'Jannie Torp','http://lorempixel.com/640/480/technics','7ed6449b-5abd-4734-8733-076e1e535b82','[{"name":"General","history":[]}]') RETURNING *;
    Executing (default): INSERT INTO "Server_User" ("userId","serverId") VALUES (1,1),(1,2),(2,3) RETURNING *;
    

    数据库中的数据记录:

    node-sequelize-examples=# select * from "server";
     id | user_id |       name        |               thumbnail                |               endpoint               |               rooms
    ----+---------+-------------------+----------------------------------------+--------------------------------------+-----------------------------------
      1 |       1 | Major Schamberger | http://lorempixel.com/640/480/abstract | ec9b17d2-6722-469f-a208-c76bc44d0cb8 | [{"name":"General","history":[]}]
      2 |       1 | Mark Cremin       | http://lorempixel.com/640/480/sports   | 59deabee-0df0-43c7-bf23-00d38eee3745 | [{"name":"General","history":[]}]
      3 |       2 | Enoch Bartoletti  | http://lorempixel.com/640/480/abstract | 765262a4-c855-412b-b496-c2d020a37e70 | [{"name":"General","history":[]}]
    (3 rows)
    
    node-sequelize-examples=# select * from "Server_User";
     userId | serverId
    --------+----------
          1 |        1
          1 |        2
          2 |        3
    (3 rows)
    
    node-sequelize-examples=# select * from "user";
     id |    username     |    password     |         email
    ----+-----------------+-----------------+------------------------
      1 | Reyes Botsford  | 7p3cEWYkpxdZM0v | Robb.Weber@hotmail.com
      2 | Micaela Kessler | G0qsV0FKNIDxAbA | Kiera66@yahoo.com
    (2 rows)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-30
      • 2017-05-06
      • 1970-01-01
      • 1970-01-01
      • 2015-08-05
      • 1970-01-01
      相关资源
      最近更新 更多