sequelize-typescript icon indicating copy to clipboard operation
sequelize-typescript copied to clipboard

Association without foreign key got ERROR Foreign key is missing

Open quaos opened this issue 3 years ago • 2 comments

Issue

Versions

  • sequelize: 6.28.0
  • sequelize-typescript: 2.1.5
  • typescript: 4.9.3

Issue type

  • [ ] bug report
  • [x] feature request

Actual behavior

Ref. Issue: #355

I'm trying to define a pair of @HasMany / @BelongsTo association without foreign key, for use with custom include / join on conditions.

But I still got the error: Foreign key for {Model1} is missing on {Model2}, even though I used the option: constraints: false.

Not sure if this is supported with Sequelize and sequelize-typescript ?

Expected behavior

Should be able to define associations without foreign keys for use with custom include/joins

Steps to reproduce

  1. Define two models
  2. Add @HasMany / @BelongsTo pairing without foreign keys
  3. Try to call Model.findAll() with include: { on: ... } option

Related code

AnonymousQuestionModel.ts

// EXAMPLE CODE

export interface AnonymousQuestionAttributes {
    // ...
}

@Table
export class AnonymousQuestionModel
  extends Model<AnonymousQuestionAttributes>
  implements AnonymousQuestionAttributes {
    @AutoIncrement
    @PrimaryKey
    @Column({ type: DataType.BIGINT })
    id!: number

   @Column
   email!: string

   @Column
   subject!: string

    @Column
    description!: string

    @BelongsTo(() => QuestionModel, { constraints: false, foreignKeyConstraint: false })
    maybeUserQuestion?: QuestionAttributes | null
}

export interface QuestionAttributes extends Omit<AnonymousQuestionAttributes, 'email'> {
    user: UserAttributes
}

QuestionModel.ts

@Table
export class QuestionModel extends Model<QuestionAttributes> implements QuestionAttributes {
    @AutoIncrement
    @PrimaryKey
    @Column({ type: DataType.BIGINT })
    id!: number

   @Column
   subject!: string

    @Column
    description!: string

    @ForeignKey(() => UserModel)
    userId!: number

    @BelongsTo(() => UserModel)
    user!: UserAttributes

    @HasMany(() => AnonymousQuestionModel, { constraints: false, foreignKeyConstraint: false })
    maybeDuplicateQuestions: AnonymousQuestionAttributes[] = []
}

QuestionsService.ts

export class QuestionService {
  constructor(protected readonly questionModel: ModelStatic<QuestionModel>) {
  }

  findAllWithDuplicates(opts: FindOptions<QuestionAttributes>) {
    return this.questionModel.findAll({
        ...opts,
        include: [
            {
                association: 'user',
            },
            {
                association: 'maybeDuplicateQuestions',
                on: {
                   [Op.and]: [
                        Sequelize.where(
                           Sequelize.col('QuestionModel.user.email'),
                           Op.eq,
                           Sequelize.col('maybeDuplicateQuestions.email')
                    ),
                    Sequelize.where(
                        Sequelize.col('QuestionModel.subject'),
                        Op.eq,
                        Sequelize.col('maybeDuplicateQuestions.subject')
                    ),
                }
            },
        ],
        order: [
            [Sequelize.col('QuestionModel.id'), 'desc'],
            [Sequelize.col('maybeDuplicateQuestions.id'), 'desc'],
        ],
    })
  }
}

quaos avatar Dec 22 '22 05:12 quaos

@quaos Did you found any solutions?

chandrashekhar07 avatar Dec 01 '23 13:12 chandrashekhar07

@quaos Did you found any solutions?

No luck. The latest workaround I'm using is adding a "dummy FK" for the relationship.

quaos avatar Dec 22 '23 08:12 quaos