node.js - 每当我尝试在 2 个模型之间创建多对多关联时,都必须为多对多自关联错误定义“as”

标签 node.js sequelize.js

我正在关注 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;

最佳答案

它适用于 "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)

关于node.js - 每当我尝试在 2 个模型之间创建多对多关联时,都必须为多对多自关联错误定义“as”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63005477/

相关文章:

node.js - 使用关联数据创建复合索引?

javascript - Sequelize 获取重复条目 : 'ER_DUP_ENTRY'

mysql - 使用关联和外键对 findAll 进行后续处理

sql - postgres/Sequelize : Edit an object in jsonb array if its property's value matches

node.js - 为什么bulkCreate 只在DB 中写入有限数量的记录(Postgres && Sequelize)

javascript - NodeJS无法识别对象的功能

javascript - AWS Lambda API 问题 "Error: Runtime exited with error: exit status 129"

javascript - 在 JavaScript 中循环遍历一个巨大的数组

mysql - Bluemix 使用 Node-RED 绑定(bind)到现有的 ClearDB MySQL 服务

javascript - 尝试使用 Request NPM 将数据从 NodeJS 发布到本地主机(Loopback Swagger API)