loopback-next icon indicating copy to clipboard operation
loopback-next copied to clipboard

Many to many relation (hasAndBelongsToMany)

Open jiwantmg opened this issue 7 years ago • 43 comments

Description / Steps to reproduce / Feature proposal

I want to implement many to many relation in loopback4 but I couldn't see the article or any documentation regarding many to many relation

jiwantmg avatar Nov 16 '18 18:11 jiwantmg

Currently it is apparently not supported (only 1-to-many [hasMany] and the reciprocal relation [belongsTo] (see https://loopback.io/doc/en/lb4/Relations.html) but I have a similar need and I'd like to know (@raymondfeng) either for when it is planned on the roadmap and/or if it is possible to contribute to speed things up (and, if so, how to contribute).

koalabi avatar Nov 19 '18 08:11 koalabi

Description / Steps to reproduce / Feature proposal

I want to implement many to many relation in loopback4 but I couldn't see the article or any documentation regarding many to many relation

+1

nm avatar Nov 19 '18 15:11 nm

Thanks for the feedback! It seems like there are more users who are looking for the other model relation types than what we have so far. As you might've known already, support of hasOne https://github.com/strongloop/loopback-next/issues/1422 is in progress. Let me discuss with @raymondfeng and team and see if there's some document to get others started on adding more relation types.

dhmlau avatar Nov 21 '18 00:11 dhmlau

cc @RaphaelDrai @elv1s

dhmlau avatar Nov 21 '18 14:11 dhmlau

Hi all, thanks for your interest in contributing to more relation types! Would like to see who has a particular interest or need for a certain relation type. Not sure what's the best way to do a poll here, I'm going to add one comment for each relation type below, and if you would like to contribute or need it for your project, please upvote. Thanks!

Here are the outstanding relation types: HasManyThrough HasAndBelongsToMany Polymorphic EmbedsOne EmbedsMany ReferencesMany

dhmlau avatar Nov 21 '18 14:11 dhmlau

  1. HasManyThrough

dhmlau avatar Nov 21 '18 14:11 dhmlau

  1. HasAndBelongsToMany

dhmlau avatar Nov 21 '18 14:11 dhmlau

  1. Polymorphic

dhmlau avatar Nov 21 '18 14:11 dhmlau

  1. EmbedsOne

dhmlau avatar Nov 21 '18 14:11 dhmlau

  1. EmbedsMany

dhmlau avatar Nov 21 '18 14:11 dhmlau

  1. ReferencesMany

dhmlau avatar Nov 21 '18 14:11 dhmlau

cc @strongloop/loopback-next @strongloop/loopback-maintainers

dhmlau avatar Nov 21 '18 14:11 dhmlau

HasManyThrough first but interested in other ones too

Le mer. 21 nov. 2018 à 15:51, Diana Lau [email protected] a écrit :

cc @strongloop/loopback-next https://github.com/orgs/strongloop/teams/loopback-next @strongloop/loopback-maintainers https://github.com/orgs/strongloop/teams/loopback-maintainers

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/strongloop/loopback-next/issues/2043#issuecomment-440690172, or mute the thread https://github.com/notifications/unsubscribe-auth/ACqwzcLwquCODmr0Jyh0bDIsRG_u0JTxks5uxWhsgaJpZM4YmxSz .

koalabi avatar Nov 21 '18 16:11 koalabi

HasManyThrough, HasAndBelongsToMany. Flick-the-switch type of Auto Update would be very nice. One that adds foreign keys automatically (which LB3 never could do), with cascade delete/restrict.

SpeedoPasanen avatar Nov 21 '18 17:11 SpeedoPasanen

How can I contribute to the manyToMany ??? I really need it.

clayrisser avatar Nov 22 '18 14:11 clayrisser

@b-admike @bajtos , what do you think is the best way to let others join forces? some content around how to get started or how the code are being organized? Thanks.

dhmlau avatar Nov 22 '18 18:11 dhmlau

I am proposing to keep this issue focused on "many to many" relation, and discuss other relation types in [EPIC] More Relations (post-GA) #1450.

From what I remember from LB3, "many to many" relation is called HasAndBelongsToMany and leverages HasManyThrough under the hood.

So I think the first step is to figure out how to implement a "hasManyThrough" relation.

In my experience so far, adding a new relation type has always been a challenge. It took multiple iterations until we were able to find a good design and a robust implementation. I expect that hasManyThrough will be similar.

In general, each relation type needs the following artifacts:

  1. A repository interface & implementation providing access to related model instances, constraining the target models to enforce the relation. See e.g. has-many.repository.ts

  2. A decorator (typically for model properties) to specify relation metadata. See e.g. has-many.decorator.ts.

  3. A repository factory that accepts the value of the foreign key and returns back the relation repository. See e.g. HasManyRepositoryFactory. https://github.com/strongloop/loopback-next/blob/f015845f60649bddfa22bdd364154ebcf029a37b/packages/repository/src/relations/has-many/has-many-repository.factory.ts#L21-L23

  4. A function to create repository factory from relation metadata. See e.g. createHasManyRepositoryFactory. https://github.com/strongloop/loopback-next/blob/f015845f60649bddfa22bdd364154ebcf029a37b/packages/repository/src/relations/has-many/has-many-repository.factory.ts#L38-L57

  5. A protected helper method in DefaultCrudRepository making it easier to setup repository factory for a named relation. See e.g. _createHasManyRepositoryFactoryFor. https://github.com/strongloop/loopback-next/blob/f015845f60649bddfa22bdd364154ebcf029a37b/packages/repository/src/repositories/legacy-juggler-bridge.ts#L172-L185

I think the steps 2-5 should be relatively straightforward because they will mostly copy the design we already have in place for "hasMany" relation. I am expecting the first step to be most challenging, as we need to find out how to implement data access operations leveraging a "through" table.

Process wise, I am proposing to start with a spike on the first step. Start designing a Repository interface and implementation that will provide the following APIs:

  • "create" a new related model
  • "find" all related models
  • "add" an existing model into relation Other methods like "delete" and "update" should be easy to add later, once we agree on the overall design & implementation strategy.

Use integration tests to test the implementation. See relation.factory.integration.ts for inspiration, but please start a new file instead.

Open a pull request as soon as you have the first method ("create"?) implemented, so that we can discuss the design & implementation early on, while there is little code written and changes are easy to make.

bajtos avatar Nov 23 '18 08:11 bajtos

Thanks @bajtos, I'll see what I can do.

clayrisser avatar Nov 23 '18 08:11 clayrisser

Hello @bajtos, I am happy to contribute with the attached design document related to the implementation of hasAndBelongsToMany relation in LB4. I am looking forward for your kind review, comments of the design document and the directives how to make progress of this document before starting the implementation contribution.

Design_HasAndBelongsToMany_Contrib.docx

RaphaelDrai avatar Dec 13 '18 18:12 RaphaelDrai

I'll be mostly away from my computer until the end of the year, I'll take a look in January. Merry Christmas! 🎄

bajtos avatar Dec 14 '18 14:12 bajtos

Merry Christmas!

RaphaelDrai avatar Dec 18 '18 18:12 RaphaelDrai

Hello @bajtos, It is important for us to have in LB4 the hasAndBelongsToMany (the direct many-to-many relation) that we are using in our LB3 application. We are actually in a transition process to move our LB3 application to LB4 and hasAndBelongsToMany is considered as an high priority. May I suggest to have a new and separated case for the hasManyThrough in order to avoid confusion with this current case?

RaphaelDrai avatar Dec 20 '18 08:12 RaphaelDrai

Hi @bajtos, Is it possible to you to get your comment/advice on the design document that I sent one month ago? Thanks, Raphael

RaphaelDrai avatar Jan 10 '19 09:01 RaphaelDrai

@dhmlau, @raymondfeng , @gczobel-f5, @bajtos
Hello, I have a question please related to hasAndBelongsToMany relation database. What is the concept in loopback for creating the relation? does the user need to create an intermediate table that defines the many-to-many relation? If not how loopback is supposed to create the relation? Thanks a lot, Raphael

Raymond Feng [6:56 PM] See https://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association

gczobel [7:21 PM] @Raymond Feng The question here is intermediate table need to be generated by the user or loopback automatically will generate a new model-repository automatically for the relationship (assembly_parts) in the example

bajtos [11:11 AM] I think LB4 should support both options:

  1. Initial experience: LB4 creates the intermediate model and repository under the hood.
  2. Advanced: the developer can supply their own intermediate model and repository to be used by HasAndBelongsToMany relation.

Implementation-wise, it may be easier to start with the advanced option, and once this is landed, then we can look into ways how to automate the creation of the intermediate model & repository.

Raphael Drai [10:58 AM] Ok, I will start first with with option 2 "Advanced". I will make change in the design document that I sent then I will re-send it for review before starting the development. Thanks a lot.

RaphaelDrai avatar Jan 27 '19 09:01 RaphaelDrai

For hasAndBelongsToMany relation type, please continue the discussion at #2308.

dhmlau avatar Jan 30 '19 17:01 dhmlau

I hope this is an appropriate place to post this question.... Is there a workaround for implementing many-to-many relationships in Loopback 4.? I think there must be since just about any significant database model will contain some number of many-to-many relationships. Without official support or a good workaround, I doubt that Loopback 4 would have been deemed ready to release otherwise. Thanks

CharlesIrvineKC avatar Apr 14 '19 15:04 CharlesIrvineKC

The HasManyThrough pull request is currently functional. There's still more work to do on it to make it more efficient with SQL, but it does work.

https://github.com/strongloop/loopback-next/pull/2359

The code for the pull request can be found at the following link.

https://github.com/codejamninja/loopback-next/tree/codejamninja/has-many-through-using-has-many

You can install it by running the following . . .

npm install --save https://github.com/codejamninja/loopback-next/releases/download/%40loopback%2Frepository-has-many-through-using-has-many/loopback-repository-has-many-through-using-has-many-1.2.1.tgz

. . . or by adding the following to the dependencies section in your package.json

    "@loopback/repository": "https://github.com/codejamninja/loopback-next/releases/download/%40loopback%2Frepository-has-many-through-using-has-many/loopback-repository-has-many-through-using-has-many-1.2.1.tgz"

clayrisser avatar Apr 15 '19 02:04 clayrisser

You can see an example of how to set it up and use it in the fixtures test.

https://github.com/codejamninja/loopback-next/tree/codejamninja/has-many-through-using-has-many/packages/repository/src/tests/fixtures

clayrisser avatar Apr 15 '19 03:04 clayrisser

For hasManyThrough, you have to explicitly define your own join (junction) table. It's very similar to the way it works in loopback 3. You can read more about it at the following link.

https://loopback.io/doc/en/lb3/HasManyThrough-relations.html

In the example I provided, the junction table is defined by the Order model. (Notice the two @belongsTo decorators.)

https://github.com/codejamninja/loopback-next/blob/codejamninja/has-many-through-using-has-many/packages/repository/src/tests/fixtures/models/order.model.ts#L30-L34

Also, notice the way Customers and Sellers are linked together through an Order with the @hasMany decorator.

https://github.com/codejamninja/loopback-next/blob/codejamninja/has-many-through-using-has-many/packages/repository/src/tests/fixtures/models/seller.model.ts#L24-L25

https://github.com/codejamninja/loopback-next/blob/codejamninja/has-many-through-using-has-many/packages/repository/src/tests/fixtures/models/customer.model.ts#L27-L28

Since this feature has not been accepted into master yet, please let me know if you have any questions or bugs.

clayrisser avatar Apr 15 '19 03:04 clayrisser

Like existing relationships in Loopback 4, you will need to wire it together in the repository.

For the hasManyThrough relationship, you use the HasManyThroughRepositoryFactory. You can see how sellers are linked to customers in the customer repository at the links below.

https://github.com/codejamninja/loopback-next/blob/codejamninja/has-many-through-using-has-many/packages/repository/src/tests/fixtures/repositories/customer.repository.ts#L41-L45

https://github.com/codejamninja/loopback-next/blob/codejamninja/has-many-through-using-has-many/packages/repository/src/tests/fixtures/repositories/customer.repository.ts#L73-L77

clayrisser avatar Apr 15 '19 03:04 clayrisser