Loopback: Relation methods for "hasMany through" with extra properties on "through" Model

Created on 13 Aug 2014  ·  16Comments  ·  Source: strongloop/loopback

Consider the example described in docs for HasManyThrough:

The “through” model, Appointment, has two foreign key properties, physicianId and patientId, that reference the primary keys in the declaring model, Physician, and the target model, Patient.

At the moment, loopback creates relation methods like Physician.patients that hides the "through" model, thus make it difficult to obtain Appointment details.

Examples

  1. To find a list of all patients and the appointment dates for a given physician (id), one has to query appointments:

GET /appointments?filter={"include":["patient"],"where":{"physicianId":2}}

It would be much nicer if one could write this instead:

GET /physicians/2/appointments?filter={"include":["patient"]} // or even better GET /physicians/2/appointments

  1. The current API makes it easy to add a new Patient to a Physician, but such call will not fill appointment date. IMO a more frequent use case is to add a new Appointment to a Physician, using an existing Patient.

At the moment, one has to add the appointment via Appointment.create(). A better API would be physician.appointments.create().

This issue is based on this StackOverflow question.

discussion feature major team-apex

Most helpful comment

+1

I've ended up creating a second relationship to access extra data stored in the join table and then have to manually re-attach it. Native support to access these properties in the primary relationship would be awesome.

"relations": {
    "conversations": {
      "type": "hasAndBelongsToMany",
      "model": "Conversation",
      "foreignKey": "",
      "through": "ConversationUserMap"
    },
    "conversationsMetadata": {
      "type": "hasMany",
      "model": "ConversationUserMap",
      "foreignKey": ""
    }
}

All 16 comments

There are two flavours of "hasMany through" relations:

  1. "hasAndBelongsToMany" relation, where the "through" model is just a container to hold the two related ids.
  2. "hasMany through", where the "through" model adds extra properties to the relation, e.g. "appointmentDate" in the example in the docs.

Initially I wanted to suggest that the solution for this GH issue must support both flavours. On the second thought, it seems to me the second flavour does not make sense: the "through" option should be used only when the "through" model is not important (does not have extra properties).

The example in the documentation should have used "Patient hasMany appointments" and "Physician hasMany appointments" instead of "Patient hasMany patients through Appointment". Or perhaps it should have specified both relations.

@raymondfeng @ritch What's your opinion? Did I miss something in my reasoning above?

@bajtos one of the things missing from 'through' relations (flavour no. 2), is allowing a REST create request (Patient for example) to specify the properties that should be stored on to the through model, in a single request.

For this, the method signature probable needs to be changed into something like:

HasManyThrough.prototype.create = function create(data, throughData, done) { ... }

Or have some kind of convention to have a special key on data to specify this 'through' data (_appointment in this case, or perhaps even _appointment):

{ name: 'John', _appointment: { date: ... } }

Taking this further, we might introduce something like Rails/AR accepts_nested_attributes_for to do this in a more generalized fashion:

http://currentricity.wordpress.com/2011/09/04/the-definitive-guide-to-accepts_nested_attributes_for-a-model-in-rails-3/

How is it going in this proposal? We really want to create the record in the through model (with extra property such as appointment date in one single API call, in order to make sure it's done in one transaction, so fail or succeed.
My guess is the suggestion from @fabien makes sense.

Or have some kind of convention to have a special key on data to specify this 'through' data (_appointment in this case, or perhaps even _appointment):

{ name: 'John', _appointment: { date: ... } }

@XinV @bajtos Is there any update on this feature? The idea of a special key (or reserved naming) to retrieve the properties of the through model, on retrieving related data would be great!

+1

I've ended up creating a second relationship to access extra data stored in the join table and then have to manually re-attach it. Native support to access these properties in the primary relationship would be awesome.

"relations": {
    "conversations": {
      "type": "hasAndBelongsToMany",
      "model": "Conversation",
      "foreignKey": "",
      "through": "ConversationUserMap"
    },
    "conversationsMetadata": {
      "type": "hasMany",
      "model": "ConversationUserMap",
      "foreignKey": ""
    }
}

Any updates on this feature? This could prove to be extremely beneficial.

还没有解决吗?

This would simplify a lot f implementations.
Any news on this?

I just released two new mixins to take care of these features:

loopback-set-through-properties-mixin allow to set through model properties

loopback-include-through-mixin allows to include model properties with queries

Related #3415 (I think, at least the solution would most likely fix the bug)

Seems there is a inconsistency in how filters are applied through "hasMany" and "hasAndBelongsToMany" relations, when M:N through a through-model

where/include are applied to the related model

order/limit are applied to the through model

This seems to be consistent between "hasMany" and "hasAndBelongsToMany" relations.

Hi, please let me know if there is any solution for this. Am actually searching for it.

Was this ever resolved with an official solution?

LoopBack version 3 is in LTS, we won't be adding any new features.

Does something like this exist in Loopback 4?

Does something like this exist in Loopback 4?

Not yet.

@marcelodive feel free to open a feature request in https://github.com/strongloop/loopback-next

Was this page helpful?
0 / 5 - 0 ratings