Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
280 views
in Technique[技术] by (71.8m points)

v4l2loopback - Loopback 4: Many to Many Relation

I am trying to implement a way to filter data in tables which have ManytoMany relationship.

I have following tables job, job_category and category.

So far I am thinking in do a query to job_category using job_id and then use that result to add a condition using IN() but I do not find any way to imp?ement this option either.

Questions:

  1. How to implement ManytoMany relation in Loopback 4?

  2. How to filter a query using IN?

PD I can use $inq for question number 2.

filter.where = {
   ...filter.where,
   id: {inq: [2, 7]},
};
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Taking the context of your question, a many-to-many relationship can be implemented in lb4 as below.

The jobs model (a sample) -

    @model({
      name: 'jobs',
    })
    export class Job extends Entity {
      @property({
        type: 'number',
        id: true,
      })
      id: number;

      @property({
        type: 'string',
        required: true,
      })
      name: string;

      // Other columns of the table.....

      constructor(data?: Partial<Job>) {
        super(data);
      }
    }

The categories model (a sample) -

    @model({
      name: 'categories',
    })
    export class Category extends Entity {
      @property({
        type: 'number',
        id: true,
      })
      id: number;

      @property({
        type: 'string',
        required: true,
      })
      name: string;

      // Other columns of the table.....

      constructor(data?: Partial<Category>) {
        super(data);
      }
    }

In the Job categories relationship model, we are going to implement the belongs to relationship with both Job and Category Models. This will ensure m:n relationship.

    @model({
      name: 'job_categories',
    })
    export class JobCategory extends Entity {
      @property({
        type: 'number',
        id: true,
      })
      id: number;

      @belongsTo(() => Job)
      job_id: number;

      @belongsTo(() => Category)
      category_id: number;

      constructor(data?: Partial<JobCategory>) {
        super(data);
      }
    }

Now, using lb4 CLI, you can create a repository and REST controller for job categories model and use the find methods there to fetch data. Unfortunately, includes parameter in Filter class for find methods is not yet implemented in lb4. Its still WIP. Refer this thread from loopback-next repo for updates. Until then, you may have to add custom logic t controller or repository classes to achieve this. Two suggested approaches from my side are below.

  1. Configure belongs to relation in repository (Refer documentation here) and use it inside controller to fetch are respond with related data (Refer implementation here). You may need to create your own response model for this. We created our own DTO for this purpose. You can also return 'any' type as response for this but that's not recommended.
  2. You can execute your own join query if needed. That's native query approach. But, unfortunately again execute function in repository class is not implemented yet. See here. Its available in dts though. So, we implemented a work around until its implemented. We created a Base repository class which will be inherited by all repository classes in our application (replacing all extends DefaultCrudRepository with extends AppDefaultCrudRepository). Here is the implementation for base repository.
    export abstract class AppDefaultCrudRepository<
      T extends Entity,
      ID
    > extends DefaultCrudRepository<T, ID> {
      constructor(
        entityClass: typeof Entity & {
          prototype: T;
        },
        dataSource: AppDataSource,
      ) {
        super(entityClass, dataSource);
      }

      execute(
        command: Command,
        parameters: NamedParameters | PositionalParameters,
        options?: Options,
      ): Promise<AnyObject> {
        // Commented below statement until it is implemented in lb4
        // return super.execute(command, parameters, options);
        return this.dataSource.execute(command, parameters, options);
      }
    }

Hope this helps with your question #1. For question #2, you already mentioned the approach. That works.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...