Как добавить 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 не помогает!) Спасибо!


Ответы (0 шт):