Skip to content

Commit

Permalink
docs: include filter
Browse files Browse the repository at this point in the history
  • Loading branch information
Agnes Lin committed Mar 27, 2020
1 parent f0e7c67 commit 52ef084
Showing 1 changed file with 226 additions and 1 deletion.
227 changes: 226 additions & 1 deletion docs/site/Include-filter.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,229 @@ source: loopback-next
file: packages/metadata/README.md
sidebar: lb4_sidebar
permalink: /doc/en/lb4/Include-filter.html
---
---

An _include_ filter enables you to include results from related models in a query over relations. (See [Relations](Relations.md) for details of defining relations)

The value of the include filter can be a string, an array, or an object.

{% include important.html content="You can use an _include_ filter with `find(),` `findOne()` and `findById()` methods.
" %}

### Node API

{% include content/angular-methods-caveat.html lang=page.lang %}

To query one relation:
```ts
{include: [{relation: 'relationName'}]}
```

To query multiple relations:
```ts
{include: [{relation: 'relationName1'}, {relation: 'relationName2'}]}
```

To query nested relations, use the scope field:

```ts
{
relation: 'relationName',
scope: {
include: [{relation: 'nestedRelationName'}],
},
}
```

Where:

- _relationName_ is the name of a relation defined in repositories. Check [Relations](Relations.md) for details.

### REST API

To query one relation:
`/modelName?filter[include][][relation]=_relationName_`

To query multiple relations:
`/modelName?filter[include][0][relation]=_relationName1_&filter[include][1][relation]=_relationName2_`

To query nested relations, as the url would get too long, we recommend to encode it with `encodeURIComponent(JSON.stringify(filter))`:
`/modelName?filter=<encodeResult>`

### Examples

- Return all customers with their orders:

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

This is equivalent to

```
GET /customers?filter[include][][relation]=orders
```

Result:

```ts
[{
id: 1,
name: 'Tom Nook',
orders:[{id: 1, desc: 'pancil'}]
},
{...}
]
```

- Return all customers with their orders and their address:

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

This is equivalent to

```
GET /customers?filter[include][0][relation]=orders?filter[include][1][relation]=address
```


Result:

```ts
[{
id: 1,
name: 'Tom Nook',
orders:[{id: 1, desc: 'pancil'}],
address: {'8200 Warden Ave'}
},
{...}
]
```

- Return all customers with their orders and also the shipment information of orders:

```ts
await customerRepository.find({
include: [
{
relation: 'orders',
scope: {
include: [{relation: 'shipment'}],
},
},
],
});
```

This is equivalent to (using `encodeURIComponent`):

```
GET /customers?filter=%7B"include"%3A%5B%7B"relation"%3A"orders"%2C"scope"%3A%7B"include"%3A%5B%7B"relation"%3A"shipment"%7D%5D%7D%7D%5D%7D
```

Result:

```ts
[{
id: 1,
name: 'Tom Nook',
orders:[
{id: 123,
desc: 'pancil',
shipment: {id: 999, company: 'UPS'} // nested related models
}
],
},
{...}
]
```

#### Combined use of `fields` and `include` for a `belongsTo` relation

If you want to use both `include` and `fields` to display only specific fields of a model and a specific belongsTo relation, **you need to add the relation foreign key in the `fields`** :

Return all posts only with field title and the relation category:
```ts
await postRepository.find({include: [{relation: 'category'}], fields: ['title', 'categoryId'});
```
#### Include with filters
In some cases, you may want to apply filters to related models to be included.
{% include note.html content="
When you apply filters to related models, the query returns results from the first model plus any results from related models with the filter query,
similar to a \"left join\" in SQL.
" %}
LoopBack supports that with the following syntax (for example):
```ts
await postRepository.find({
include: [{
relation: 'owner'// include the owner object
scope: { // further filter the owner object
fields: ['username', 'email'], // only show two fields
include: { // include orders for the owner
relation: 'orders'
scope: {
where: {orderId: 5} // only select order with id 5
}
}
}
}]
});
```
For real-world scenarios where only users in `$authenticated` or `$owner` roles should have access, use `findById()`.
For example, the following example uses filters to perform pagination:
```ts
await postRepository.findById('123', {
include: [{
relation: 'owner',
scope: { // fetch 1st "page" with 5 entries in it
skip:0,
limit:5
}
}]
});
```
#### Access included objects
In the Node.js API, call `toJSON()` to convert the returned model instance with related items into a plain JSON object. For example:
```ts
const result = await postRepository.find({include: [{relation: 'owner'}, {relation: 'orders'}]});
console.log(result.owner.posts, result.owner.orders);
//... 
```
Note the relation properties such as `post.owner` reference a JavaScript **function** for the relation method.
#### REST examples
These examples assume a customer model with a hasMany relationship to a reviews model. 
Return all customers including their reviews:
`/customers?filter[include][][relation]=reviews`
Return all customers including their reviews and also their orders:
`GET /`customers?filter[include][0][relation]=reviews?filter[include][1][relation]=orders`

Return all customers whose age is 21, including their reviews:

`/customers?filter[include][][relation]=reviews&filter[where][age]=21`

Return first two customers including their reviews:

`/customers?filter[include][][relation]=reviews&filter[limit]=2`

**See also**: [Querying related models](HasMany-relation.md#querying-related-models).

0 comments on commit 52ef084

Please sign in to comment.