nestjsx / crud

NestJs CRUD for RESTful APIs
https://github.com/nestjsx/crud/wiki
MIT License
4.09k stars 540 forks source link

Problems with nested controller routes / nested route params #583

Open Jtosbornex opened 4 years ago

Jtosbornex commented 4 years ago

I have used this library in conjunction with nestjs for almost a year now. Nest by istelf for 2, so I am fairly familiar with the API of both. Thank you for this work as it has been very nice to use overall.


https://github.com/nestjsx/crud/wiki/Controllers#get-one-resource

First off I think there may be a bug in the documentation:

image

It looks like you are missing a forward slash after perks.


Secondly, I have not been able to get nested routes to work at any point. An example of a nested route being something such as this:

/heroes/:heroId/perks/:id

The documentation kind of explains for this case:

If you have a controller path with that looks kinda similar to this /companies/:companyId/users you need to add this param option: @Crud({ ... params: { ... companyId: { field: 'companyId', type: 'number' }, }, ... })

But it doesn't show you what the entities look like on the back end to make this happen. I think this is of key importance to get this to work.

This part of the documentation is seriously lacking. If I could get this feature to work I would consider adding a PR, but like I said, I have yet to be able to use this feature.

baptadn commented 4 years ago

Here is a working example of nested routes :) https://github.com/shinework/nest-crud-nested-controller

Jtosbornex commented 4 years ago

@shinework I appreciate the example. This is very helpful.

So I see two main takeaways from your articles controller: image

  1. The controller has the nested route listed explicitly. I incorrectly thought this was possible in the authors controller, but this makes sense.

@Controller('/authors/:id/articles')

  1. You are listing the author id in the params of the articles controller. Since I was working under the assumption this would be in the authors controller, when I followed this step obviously nothing happened. ... params: { id: { field: 'author', type: 'number', }, }, ...

My only question for you now is this eager join necessary in the author controller?

under image

baptadn commented 4 years ago

Hello @Jtosbornex! No, the eager join is not mandatory. Checkout my latest commit because there was an issue in my previous commit :

https://github.com/shinework/nest-crud-nested-controller

@Crud({
  model: {
    type: Article,
  },
  params: {
    authorId: {
      field: 'authorId',
      type: 'number',
    },
  },
})
@ApiTags('articles')
@Controller('/authors/:authorId/articles')
export class ArticleController implements CrudController<Article> {
  constructor(public service: ArticleService) {}
}

And you have to explicitly add a authorId field :

import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm'
import { Author } from '../author/author.entity'
import { ApiProperty } from '@nestjs/swagger'

@Entity()
export class Article {
  @PrimaryGeneratedColumn()
  id: number

  @Column('text')
  content: string

  @ApiProperty({ type: () => Author })
  @ManyToOne(
    () => Author,
    author => author.articles,
  )
  author: Author

  @Column()
  authorId: number
}

Calling http://localhost:3000/authors/1/articles/3 results to:

SELECT "Article"."id" AS "Article_id", "Article"."content" AS "Article_content", "Article"."authorId" AS "Article_authorId" 
FROM "article" "Article" 
WHERE ("Article"."authorId" = $1 AND "Article"."id" = $2) -- PARAMETERS: [1,3]

http://localhost:3000/authors/1/articles:

SELECT "Article"."id" AS "Article_id", "Article"."content" AS "Article_content", "Article"."authorId" AS "Article_authorId" 
FROM "article" "Article" 
WHERE ("Article"."authorId" = $1) -- PARAMETERS: [1]

🤘

Jtosbornex commented 4 years ago

@shinework thank you for this minimal example. I will definitely be able to use this pattern now because of your comments!

maxshilov commented 3 years ago

@shinework Thank you for example. Did you see something similar for mongoose and MongoDB?

avchugaev commented 3 years ago

What's the point in creating an additional field?

I need it to work normally with JoinColumn:

image

Is that possible?

Jtosbornex commented 3 years ago

@avchugaev

I think you need to explicitly add in the following:

@Column() school_id:number;

avchugaev commented 3 years ago

@Jtosbornex thanks, it solved my problem. But to be honest, the solution is a bit unexpected. 😉

talhazafar444 commented 3 years ago

Hi @shinework , loved your answer. But I got a problem in not equal to scenario. e.g. I want records where authorId is not equal (!=) to the params.authorId. or how do I use params value in query.filter?

Jtosbornex commented 3 years ago

@talhazafar444 so you want the route

GET /authors/:authorId/articles

to give you all of the articles for authors that do not have id = :authorId ?

This seems like it would make more sense to do on the articles getMany endpoint

GET /articles

Then you can you use the requests library to create your query params

https://github.com/nestjsx/crud/wiki/Requests#filter

or use something like this if you are constructing the URL manually.

GET /articles?filter=authorId||$neq||12345

where 12345 is the id for the author you dont want.

raphaelsoul commented 2 years ago

does it works for M2M relations?