Custom or override join in Sequelize.js

こ雲淡風輕ζ 提交于 2019-12-22 17:54:29

问题


I need to create a custom join condition using Sequelize.js with MSSQL. Specifically, I need to join TableB based on a COALESCE value from columns in TableA and TableB and end up with a join condition like this:

LEFT OUTER JOIN [TableB]
    ON [TableB].[ColumnB] = COALESCE (
        [TableC].[ColumnC],
        [TableA].[ColumnA]
    )

I'd settle for an OR clause in my join:

LEFT OUTER JOIN [TableB]
    ON [TableB].[ColumnB] = [TableA].[ColumnA]
    OR [TableB].[ColumnB] = [TableC].[ColumnC]

I read that you can achieve behaviour like this by including required: false in your scope definition. As you can see, I've plastered my scope with it attempting to get this to work.

The best I could get is this (note the AND clause):

LEFT OUTER JOIN [TableB]
    ON [TableB].[ColumnB] = [TableA].[ColumnA]
    AND [TableB].[ColumnB] = COALESCE (
        [TableC].[ColumnC],
        [TableA].[ColumnA]
    )

If I were using MySQL, I think I could simply use the COALESCE value from the SELECT in the JOIN and be good to go but in my prior research read that it was required to recalculate the value.

I've included a stripped down model definition for TableA:

export default (sequelize, DataTypes) => sequelize.define('TableA',
    {
        // Attributes omitted..
    },
    {
        classMethods: {
            associate ({
                TableB,
                TableC
            }) {
                this.belongsTo(TableB, {
                    foreignKey: 'ColumnA',
                    targetKey: 'ColumnB'
                });

                this.belongsTo(TableC, {
                    foreignKey: 'ColumnA',
                    targetKey: 'ColumnC'
                });
            },
            attachScope ({
                TableB,
                TableC
            }) {
                this.addScope('defaultScope', {
                    attributes: [
                        ...Object.keys(this.attributes),
                        [
                            sequelize.fn(
                                'COALESCE',
                                sequelize.col('[TableC].[ColumnC]'),
                                sequelize.col('[TableA].[ColumnA]')
                            ),
                            'ColumnA'
                        ]
                    ],
                    include: [
                        {
                            model: TableB,
                            where: {
                                ColumnB: sequelize.fn(
                                    'COALESCE',
                                    sequelize.col('[TableC].[ColumnC]'),
                                    sequelize.col('[TableA].[ColumnA]')
                                )
                            },
                            required: false
                        },
                        {
                            model: TableC,
                            required: false
                        }
                    ],
                    required: false
                }, { override: true });
            }
        }
    }
);

Any assistance would be greatly appreciated, and if any additional information is required please let me know.

Note: I'm working with a legacy database and unfortunately cannot change the data structure.


回答1:


Hi I had the same issue and finally I solved using a SQL pure query.

Example:

const query = `SELECT s.*, us.UserId \
                FROM UserSections AS us \
                RIGHT JOIN Sections AS s ON (s.id = us.SectionId) \
                WHERE s.parentId = ${sectionId}`;

return db.query(query, { type: db.QueryTypes.SELECT });

The problem is that this function will return a IMyType instead of IMyTypeInstance

Can it works for you??



来源:https://stackoverflow.com/questions/41467135/custom-or-override-join-in-sequelize-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!