Skip to content

Commit

Permalink
docs: add docs for inclusion resolver for has many
Browse files Browse the repository at this point in the history
  • Loading branch information
Agnes Lin committed Sep 10, 2019
1 parent dd743a1 commit c545033
Showing 1 changed file with 113 additions and 0 deletions.
113 changes: 113 additions & 0 deletions docs/site/HasMany-relation.md
Original file line number Diff line number Diff line change
Expand Up @@ -314,3 +314,116 @@ certain properties from the JSON/OpenAPI spec schema built for the `requestBody`
payload. See its [GitHub
issue](https://github.com/strongloop/loopback-next/issues/1179) to follow the discussion.
" %}

## Querying related models

Loopback4 has the concept of `inclusion resolver` in relations, which helps to
query data through include filter. An inclusion resolver is a function that can
fetch target models for the given list of source model instances. LB4 creates a
different inclusion resolver for each relation type.

The following is an example for has-many inclusion resolver:

- Model `Customer`
- Model `Order`
- `Customer` has mamy `Order`

```ts
// import statements
class Customer extends Entity {
// property definition for id, name
@hasMany(() => Order, {keyTo: 'customerId'})
orders?: Order[];
}
```

```ts
// import statements
class Order extends Entity {
// property definition for id, name
@property({
type: 'number',
})
customerId?: number;
// constructor, relation, etc
}
```

The inclusion resolver allows users to retrieve all customer along with all
related orders by the following code:

```ts
categoryRepo.find({include: [{relation: 'products'}]});
```

### Enable/disable the inclusion resolvers:

- Base repository classes have a public property `inclusionResolvers`, which
maintains a map containing inclusion resolvers for each relation.
- The inclusion resolver `inclusionResolver` of a certain relation is built when
the source repository class calls the `createHasManyRepositoryFactoryFor`
function in the constructor with the relation name.
- Call `registerInclusionResolver` to add the resolver of that relation to the
`inclusionResolvers` map. (As we realized in LB3, not all relations are
allowed to be traversed. Users can decide to which resolvers can be added.)

The following code snippet shows how it would look like for registering the
inclusion resolver for has many relation 'orders':

```ts
export class CustomerRepository extends DefaultCrudRepository {
products: HasManyRepositoryFactory<Order, typeof Customer.prototype.id>;

constructor(
dataSource: juggler.DataSource,
orderRepositoryGetter: Getter<OrderRepository>,
) {
super(Customer, dataSource);

// we already have this line to create HasManyRepository factory
this.orders = this.createHasManyRepositoryFactoryFor(
'orders',
orderRepositoryGetter,
);

// add this line to register inclusion resolver
this.registerInclusion('orders', this.orders.inclusionResolver);
}
}
```

- We can simply include the relation in queries via find(), findOne(),
findById() methods. Example:

```
customerRepository.find({include: [{relation: 'orders'}]});
```

which returns:

```ts
[
{
id: 1,
name: 'Thor',
orders:[{name: 'Mjolnir', customerId: 1}, {name: 'Rocket Raccoon', customerId: 1}]
},
{
id: 2,
name: 'Captain',
orders:[{name: 'Shield', customerId: 2}]
},
...
]
```

- You can delete a relation from `inclusionResolvers` to disable the inclusion
for a certain relation. e.g
`customerRepository.inclusionResolvers.delete('orders')`

{% include note.html content="
Inclusion with custom scope:
Besides specifying the relation name to include, it's also possible to specify additional scope constraints.
However, this feature is not supported yet. Check our GitHub issue for more information:
[Include related models with a custom scope](https://github.com/strongloop/loopback-next/issues/3453).
" %}

0 comments on commit c545033

Please sign in to comment.