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

Sequelize `get({ plain: true })` or `toJSON()` doesn't work with associations

Open mopcweb opened this issue 3 years ago • 5 comments

Hi! Thanks for your effort and this lib!

Issue

I've been using sequelize-typescript for some time and noticed, that associations are not added to dataValues of native Sequelize object when fetching any records. Because of this, after calling Sequelize.get({ plain: true }) or Sequelize.toJSON() - there is no association data in resulting object.

Versions

  • sequelize: 5.22.2
  • sequelize-typescript: 1.1.0
  • typescript:

Issue type

  • [x] bug report

Actual behavior

const result = SomeModel.findByPk(1, { include: [AnotherModel] });
console.log(result.get({ plain: true }).anotherModel // undefined

Expected behavior

console.log(result.get({ plain: true }).anotherModel // here should be an object for AnotherModel record.

Steps to reproduce


@Table({ tableName: 'First' })
export class First extends Model<IFirst> implements IFirst {
  @PrimaryKey
  @AutoIncrement
  @Column
  public id: number;

  @Column
  public title: string;
}

export class Second extends Model<ISecond> implements ISecond {
  @PrimaryKey
  @AutoIncrement
  @Column
  public id: number;

  @Column
  public title: string;

  @ForeignKey(() => First)
  @Column
  public firstId: number;

  @BelongsTo(() => First)
  public first: IFirst;
}

export interface IFirst { id: string; title: string }

export interface ISecond { id: string; title: string }

async function test(): Pormise<void> {
  const result = await Second.findByPk(1, { include: [First] });
  console.log(result.get({ plain: true }).first); // indefined
  console.log(result.toJSON().first); // indefined
}

a bit similar to https://github.com/RobinBuschmann/sequelize-typescript/issues/605

mopcweb avatar Mar 09 '21 13:03 mopcweb

Found temporary solution - use raw: true and nest: true in query. raw: true - will return plain object instead of Model instance, but there won't be nested objects for associations. nest: true - will map properties of type: 'first.title': 'someValue' to first: { title: 'someValue' }.

Second.findByPk(1, { include: [First], raw: true, first: true });

image

mopcweb avatar Mar 09 '21 15:03 mopcweb

are there any updates?(

mopcweb avatar Jul 28 '21 15:07 mopcweb

I either use Second.findByPk(1, { include: [First], raw: true, first: true }); Like you mention above or I overwrite the toJSON function for my models to always call the associations.


@Table({ tableName: 'First' })
export class First extends Model<IFirst> implements IFirst {
  @PrimaryKey
  @AutoIncrement
  @Column
  public id: number;

  @Column
  public title: string;
}

export class Second extends Model<ISecond> implements ISecond {
  @PrimaryKey
  @AutoIncrement
  @Column
  public id: number;

  @Column
  public title: string;

  @ForeignKey(() => First)
  @Column
  public firstId: number;

  @BelongsTo(() => First)
  public first: IFirst;
  
  toJSON(): object {
    return { ...this.get(), first: this.first }
  }
}

export interface IFirst { id: string; title: string }

export interface ISecond { id: string; title: string }

async function test(): Pormise<void> {
  const result = await Second.findByPk(1, { include: [First] });
  console.log(result.toJSON().first);
}

lwileczek avatar Mar 06 '23 20:03 lwileczek

after dozens of different "hacks" i get to next - ORMs in JS r so inmature :( if orm is smth necessary - better to use typeorm instead of sequelize. but still - much better - just query builder and raw sql queries - orms are no way for complex queries :(

mopcweb avatar Mar 13 '23 23:03 mopcweb

you can run a raw query if you cannot get exactly what you want: https://sequelize.org/docs/v6/core-concepts/raw-queries/

lwileczek avatar Mar 14 '23 13:03 lwileczek