我正在测试带有sequelize的所有关联,但是遇到一个问题,要使用belongsToMany获得很多对很多的联接。
https://github.com/lhferrh/Sequelize-Playground.git
当我执行findAll时,我得到联接结果的所有null
我一直在检查几种组合,但问题是sequelize生成的SQL直接在MySQL上运行,这让我感到非常困惑。
这是提供的sql:
SELECT `user`.`userId`, `user`.`name`, `user`.`createdAt`, `user`.`updatedAt`, `cars`.`carId` AS `cars.carId`, `cars`.`make` AS `cars.make`, `cars`.`createdAt` AS `cars.createdAt`, `cars`.`updatedAt` AS `cars.updatedAt`, `cars->favorites`.`favoritesId` AS `cars.favorites.favoritesId`, `cars->favorites`.`date` AS `cars.favorites.date`, `cars->favorites`.`createdAt` AS `cars.favorites.createdAt`, `cars->favorites`.`updatedAt` AS `cars.favorites.updatedAt`, `cars->favorites`.`userId` AS `cars.favorites.userId`, `cars->favorites`.`carId` AS `cars.favorites.carId` FROM `users` AS `user` LEFT OUTER JOIN ( `favorites` AS `cars->favorites` INNER JOIN `cars` AS `cars` ON `cars`.`carId` = `cars->favorites`.`carId`) ON `user`.`userId` = `cars->favorites`.`userId`;
这是我正在运行的代码:
const Users = sequelize.define('user', {
userId: {
type: Sequelize.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
name: {
type: Sequelize.STRING,
},
}
);
const Favorites = sequelize.define('favorites', {
favoritesId: {
type: Sequelize.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
date: {
type: Sequelize.DATE,
}
}
);
const Cars = sequelize.define('cars', {
carId: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
make: Sequelize.STRING
})
Users.belongsToMany(Cars, {
through: 'favorites',
sourceKey: 'userId',
foreignKey: 'userId'
});
Cars.belongsToMany(Users, {
through: 'favorites',
sourceKey: 'carId',
foreignKey: 'carId'
});
const intiDataBase = async () => {
await sequelize.sync({force: true});
}
const run = async () => {
const max = 3;
await intiDataBase();
await Promise.all( DATA.users.map( async elem=>
Users.create({...elem})
))
await Promise.all( DATA.cars.map( async elem =>
Cars.create({...elem})
))
for( let i = 0 ; i < 5 ; i++ ){
Favorites.create({
userId: getRandomInt(1 , max),
carId: getRandomInt(0, max)
})
}
const car = await Users.findAll({
include: [{
model: Cars,
through: {
attributes: ['userId', 'carId'],
}
//attributes: ['make'],
}],
raw: true
});
const favorites = await Favorites.findAll({
where:{
userId:2
},
raw: true
});
console.log(car);
console.log(favorites);
}
run();
这是我得到的结果
name: 'Johan',
createdAt: 2019-10-05T08:57:57.000Z,
updatedAt: 2019-10-05T08:57:57.000Z,
'cars.carId': null,
'cars.make': null,
'cars.createdAt': null,
'cars.updatedAt': null,
'cars.favorites.favoritesId': null,
'cars.favorites.date': null,
'cars.favorites.createdAt': null,
'cars.favorites.updatedAt': null,
'cars.favorites.userId': null,
'cars.favorites.carId': null } ], ...
这可能是一个命名问题,但是SQL直接起作用的事实确实令人困惑。
我希望你们中的任何人都能看到错误。
顺便说一句,我还想知道通过创建两个与中间表的1:m关联来手动创建多对多关系的缺点是什么?
答案 0 :(得分:0)
我发现了我的错误。将收藏夹插入数据库时,缺少等待。因此,联接在查询中给出错误的结果,并在数据库中直接给出正确的结果。
for( let i = 0 ; i < 5 ; i++ ){
await Favorites.create({
userId: getRandomInt(1 , max),
carId: getRandomInt(0, max)
})
}
正如我期望的那样,这是一个愚蠢的错误。
无论如何,我还是对自己使用belongToMany还是自己创建多对多关系感到犹豫,并且总是使用两个步骤。