Как добавить Join в sequelize
У меня есть таблица appFields у нее рекурсивная структура
| id | main_id | slug | name | createdAt | updatedAt |
|---|---|---|---|---|---|
| 1 | NULL | tag | Tags | 2023-11-30 00:23:50 | 2023-11-30 00:23:50 |
| 2 | 1 | NULL | All inclusive | 2023-11-30 00:24:21 | 2023-11-30 00:24:21 |
| 3 | 1 | NULL | Airface included | 2023-11-30 00:24:51 | 2023-11-30 00:24:51 |
| 4 | 1 | NULL | No change fee | 2023-11-30 00:24:54 | 2023-11-30 00:24:54 |
| 5 | 1 | NULL | FullRefundable | 2023-11-30 00:24:56 | 2023-11-30 00:24:56 |
| 6 | NULL | amenity | Amenities | 2023-11-30 00:27:51 | 2023-11-30 00:27:52 |
| 7 | 6 | NULL | Gym | 2023-11-30 00:28:26 | 2023-11-30 00:28:26 |
| 8 | 6 | NULL | Cribs | 2023-11-30 00:28:44 | 2023-11-30 00:28:44 |
| 9 | NULL | meal_plan | Meal Plans Available | 2023-11-30 00:29:33 | 2023-11-30 00:29:33 |
| 10 | 9 | Breakfast included | 2023-11-30 00:30:14 | 2023-11-30 00:30:14 | |
| 11 | 9 | Lunch included | 2023-11-30 00:30:43 | 2023-11-30 00:30:43 | |
| 12 | 9 | Dinner included | 2023-11-30 00:30:45 | 2023-11-30 00:30:46 |
У меня есть запрос который генерируется с помощью sequelize Вот два запроса который мне генерирует фреймворк, ниже объясню почему 2
-- Запрос Первый
SELECT `appPost`.`id`,
`appPost`.`slug`,
`appPost`.`title`,
`appPost`.`postType`,
`appPost`.`priceTotal`,
`appPost`.`priceWas`,
`appPost`.`dateStart`,
`appPost`.`dateEnd`,
`appPost`.`top`,
`appPost`.`createdAt`,
`appPost`.`updatedAt`,
`appPostType`.`id` AS `appPostType.id`,
`appPostType`.`slug` AS `appPostType.slug`,
`appPostType`.`name` AS `appPostType.name`,
`appPostType`.`createdAt` AS `appPostType.createdAt`,
`appPostType`.`updatedAt` AS `appPostType.updatedAt`,
`appFields`.`id` AS `appFields.id`,
`appFields`.`main_id` AS `appFields.main_id`,
`appFields`.`slug` AS `appFields.slug`,
`appFields`.`name` AS `appFields.name`,
`appFields`.`createdAt` AS `appFields.createdAt`,
`appFields`.`updatedAt` AS `appFields.updatedAt`
FROM `appPosts` AS `appPost`
LEFT OUTER JOIN `appPostTypes` AS `appPostType` ON appPost.postType
LEFT OUTER JOIN (`connectionPostFields` AS `appFields->connectionPostField` INNER JOIN `appFields` AS `appFields`
ON `appFields`.`id` = `appFields->connectionPostField`.`appFieldId`)
ON `appPost`.`id` = `appFields->connectionPostField`.`appPostId`
WHERE `appFields`.`id` IN ('2', '7', '4')
GROUP BY `appPost`.`id`
HAVING COUNT(DISTINCT appFields.id) = 3
LIMIT 5 OFFSET 0;
-- Запрос Второй
SELECT `appPost`.`id`,
`appPost`.`slug`,
`appPost`.`title`,
`appPost`.`postType`,
`appPost`.`priceTotal`,
`appPost`.`priceWas`,
`appPost`.`dateStart`,
`appPost`.`dateEnd`,
`appPost`.`top`,
`appPost`.`createdAt`,
`appPost`.`updatedAt`,
`appPostType`.`id` AS `appPostType.id`,
`appPostType`.`slug` AS `appPostType.slug`,
`appPostType`.`name` AS `appPostType.name`,
`appPostType`.`createdAt` AS `appPostType.createdAt`,
`appPostType`.`updatedAt` AS `appPostType.updatedAt`,
`appFields`.`id` AS `appFields.id`,
`appFields`.`main_id` AS `appFields.main_id`,
`appFields`.`slug` AS `appFields.slug`,
`appFields`.`name` AS `appFields.name`,
`appFields`.`createdAt` AS `appFields.createdAt`,
`appFields`.`updatedAt` AS `appFields.updatedAt`
FROM `appPosts` AS `appPost`
LEFT OUTER JOIN `appPostTypes` AS `appPostType` ON appPost.postType
LEFT OUTER JOIN (`connectionPostFields` AS `appFields->connectionPostField` INNER JOIN `appFields` AS `appFields`
ON `appFields`.`id` = `appFields->connectionPostField`.`appFieldId`)
ON `appPost`.`id` = `appFields->connectionPostField`.`appPostId`
WHERE `appPost`.`id` IN (1);
Вот Файл моделей model.js
const { sequelize, DataTypes, Op } = require('../config')
const appPost = sequelize.define('appPost', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
slug: {
type: DataTypes.TEXT,
allowNull: false,
},
title: {
type: DataTypes.TEXT,
allowNull: false,
},
postType: {
type: DataTypes.INTEGER,
allowNull: false,
},
priceTotal: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: 0,
},
priceWas: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: 0,
},
dateStart: {
type: DataTypes.DATE,
allowNull: false,
},
dateEnd: {
type: DataTypes.DATE,
allowNull: false,
},
top: {
type: DataTypes.BOOLEAN,
allowNull: false,
}
})
const appPostType = sequelize.define('appPostType', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
slug: {
type: DataTypes.TEXT,
allowNull: false,
},
name: {
type: DataTypes.TEXT,
allowNull: false,
},
})
const appField = sequelize.define('appField', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
main_id: {
type: DataTypes.INTEGER,
defaultValue: null,
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
},
slug: {
type: DataTypes.TEXT,
defaultValue: null,
},
name: {
type: DataTypes.TEXT,
allowNull: false,
},
})
const connectionPostField = sequelize.define('connectionPostField')
// Определение связей между моделями
appPost.belongsTo(appPostType, { foreignKey: 'postType' })
appField.belongsTo(appField, {
as: 'parent',
foreignKey: 'main_id',
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
});
appPost.belongsToMany(appField, { through: connectionPostField })
appField.belongsToMany(appPost, { through: connectionPostField })
// Определение ассоциаций
appPost.hasMany(connectionPostField, { foreignKey: 'appPostId' });
connectionPostField.belongsTo(appPost, { foreignKey: 'appPostId' });
connectionPostField.belongsTo(appField, { foreignKey: 'appFieldId' });
appField.hasMany(connectionPostField, { foreignKey: 'appFieldId' });
sequelize.sync()
module.exports = {
sequelize,
Op,
appPost,
appPostType,
appField,
connectionPostField
}
Вот файл исполняемый index.js
const {
Op,
appPost,
appPostType,
appField,
connectionPostField
} = require('./model')
const { sequelize } = require('../config')
module.exports = {
getPost: async function (param) {
try {
let getJoins = [
{
model: appPostType,
required: false,
on: { id: sequelize.literal('appPost.postType') },
},
{
model: appField,
through: {
attributes: [] // Отключаем атрибуты связи
},
required: false,
on: {
id: sequelize.literal('appFields.id')
},
},
]
let subQuery = param.field ? await appPost.findAll({
include: getJoins,
where: {
'$appFields.id$': {
[Op.in]: param.field,
}
},
group: ['appPost.id'],
having: sequelize.literal('COUNT(DISTINCT appFields.id) = '+param.field.length+' '+param.limit+' '+param.offset),
}) : false
let posts = await appPost.findAll({
include: getJoins,
where: subQuery ? {
id: { [Op.in]: subQuery.map(item => item.id) }
} : undefined
})
return posts
} catch (error) {
console.error(error)
return false
}
}
}
И так два запроса потому как первый для фильтрации и определения id которые нужны, та-же работает limit и offset если это нужно, второй это уже для филдов которые есть у поста
Мой вопрос Как добавить include (он же Join) для того чтобы можно было увидеть slug id name парента (родительского филда) Например есть филд All inclusive, у него есть Парент Tags Мне нужно как-то приджоинить чтобы было видно парента, сделать запрос на SQL я могу, а вот на sequelize собрать этот запрос сложновато, возможно кто-то знает как это сделать, плиз отзовитесь, ато уже целый день работаю над этим и чат GPT не помогает!) Спасибо!