Skip to content

Commit

Permalink
feat(repository): implement inclusionResolver for hasMany
Browse files Browse the repository at this point in the history
Co-authored-by: Miroslav <[email protected]>
Co-authored-by: Nora <[email protected]>
  • Loading branch information
3 people committed Sep 12, 2019
1 parent ae462b4 commit b77f8a9
Show file tree
Hide file tree
Showing 13 changed files with 864 additions and 11 deletions.
115 changes: 115 additions & 0 deletions docs/site/HasMany-relation.md
Original file line number Diff line number Diff line change
Expand Up @@ -314,3 +314,118 @@ 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

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

The following is an example for a HasMany inclusion resolver:

- Two models: `Customer` and `Order`
- A `Customer` has many `Order`s

```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
}
```

After setting up the relation in the repository class, the inclusion resolver
allows users to retrieve all customers along with their related orders through
the following code:

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

### Enable/disable the inclusion resolvers:

- Base repository classes have a public property `inclusionResolvers`, which
maintains a map containing inclusion resolvers for each relation.
- The `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 to register the inclusion resolver for the
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 a 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()`, and
`findById()` methods. Example:

```ts
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).
" %}
1 change: 1 addition & 0 deletions packages/repository-tests/src/crud-test-suite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export function crudRepositoryTestSuite(
freeFormProperties: true,
emptyValue: undefined,
supportsTransactions: true,
supportsInclusionResolvers: true,
...partialFeatures,
};

Expand Down
Loading

0 comments on commit b77f8a9

Please sign in to comment.