NestJS – Sequelize (using TypeScript wrapper) – many to many

Posted: February 12, 2020 in NestJS
Tags: , , , ,

Here i will shortlly describe how to create many to many relationship between, for example, author and its books – book and its authors.

How to create entities is described on the github page of “sequelize-typescript”, here is a link:
https://github.com/RobinBuschmann/sequelize-typescript#many-to-many

This is the description from the link above

After you added @BelongsToMany section to Author and Book entities and created entitiy BookAuthor, you have to create provider for BookAuthor entity. And of course you have to add BookAuthor entity to the sequelize models.
After that you can run app and you should have a new table in database, called BookAuthors, with two foreign keys pointing to table Book and Author.

How to use many to many

In my example I created two API end points, one to assign a book to an author and another one to get author with books.

In my AuthorsService I injected booksAuthorsRepository, then i could use it to assign book to an author like this:

Method to assign book to author

Now after you assign some books to an author, you also want to get those books with author, right? So, I don’t always want to get books with author, that is why I created separate method to get one author with books. Here it is:

Include books with an author


Note: to be able to use include, you should not set query option raw to true, because it will crash. You can read more about this here: https://github.com/sequelize/sequelize/issues/6408

Serialization of author with books

You will noticed that after you get an author with books from your API, the book objects will have propery BookAuthor, from your Book class, mapped to it.
So at this point, I think its time to research Serialization – Exclude properties section in NestJS documentation: https://docs.nestjs.com/techniques/serialization

GitHub repository

A have created repository with example.
The whole API that I want to create is still in the making, so here is the link to the commit with things described in this article:
https://github.com/bozjator/bookshelf-api/commit/c8162444e81046ab5033893e3eac93e2162a10c8

And here is the link if you want to explore the whole repository at the time of the above commit:
https://github.com/bozjator/bookshelf-api/tree/c8162444e81046ab5033893e3eac93e2162a10c8

Comments
  1. Felix Cabrera says:

    ApplicationState model
    @BelongsToMany(() => Person, () => ActualApplicationState)
    personActual: Array;

    Person model
    @BelongsToMany(() => ApplicationState, () => ActualApplicationState)
    stateActual: Array;

    ActualApplicationState model
    @Column({
    primaryKey: true,
    autoIncrement: true,
    type: DataType.BIGINT
    })
    id!: number;

    @ForeignKey(() => Person)
    @Column({
    field: ‘person_id’,
    type: DataType.BIGINT
    })
    personID!: number;

    @ForeignKey(() => ApplicationState)
    @Column({
    field: ‘state_id’,
    type: DataType.BIGINT
    })
    stateID!: number;

    Query
    const exists: Person = await this.personModel.findByPk(id, {
    include: [
    { model: ApplicationState, as: ‘stateActual’ }
    ],
    raw: true,
    nest: true
    });

    Response
    {
    “id”:111111111111,
    “stateActual”: {
    “id”: 8,
    “version”: 0,
    “companyId”: 1,
    “name”: “Disponible”,
    “selectable”: {
    “type”: “Buffer”,
    “data”: [
    1
    ]
    },
    “ActualApplicationState”: {
    “id”: 1334,
    “version”: 4,
    “lastUpdated”: “2018-06-25T10:14:23.000Z”,
    “personID”: 537,
    “stateID”: 8
    }
    }
    }

    Only one result like an Object instead Array (I have 3 person_id in actual_application_state table)

    Please Help me!

    • bozjator says:

      Take a look at your query part, where you are calling this.personModel.findByPk which will return only one item. Use findAll instead of findByPk to get all of them.

Leave a Reply

Your email address will not be published. Required fields are marked *