docs/site/Include-filter.md
An include filter enables you to include results from related models in a query over relations. (See Relations for details on how to define 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.
" %}
To query one relation:
{
include: ['relationName'];
}
or
{
include: [{relation: 'relationName'}];
}
To query multiple relations:
{
include: ['relationName1', 'relationName2'];
}
or
{
include: [{relation: 'relationName1'}, {relation: 'relationName2'}];
}
To query nested relations, use the scope field:
{
relation: 'relationName',
scope: {
include: ['nestedRelationName'],
},
}
Where:
To query one relation: /modelName?filter[include][]=_relationName_ or
/modelName?filter[include][][relation]=_relationName_
To query multiple relations:
/modelName?filter[include][0]=_relationName1_&filter[include][1]=_relationName2_
or
/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>
You can also use stringified JSON format in a REST query.
Please note if the scope filter contains non-string data, they won't be coerced if you use the plain query. Only the stringified JSON format works as expected.
For example, the following REST query which includes related users without
their names:
/modelName?filter[include][0][relation]=users&filter[include][0][scope][fields][name]=false
won't hide the name field for users, because false is a boolean value. It
won't be coerced and will present as a string when passed to the controller
function.
A solution is to use the stringified JSON query instead to include data with scope specified:
// Define the inclusion filter and get its encoded format
const inclusionFilter = {
include: {
relation: 'users',
scope: {
fields: {name: false},
},
},
};
const encodedFilter = encodeURIComponent(JSON.stringify(inclusionFilter));
and call /modelName?filter=<encodedFilter>
{% include code-caption.html content="Node.js API" %}
await customerRepository.find({include: ['orders']});
{% include code-caption.html content="REST" %}
/customers?filter[include][]=orders
Or stringified JSON format:
/customers?filter={"include":["orders"]}
Result:
[{
id: 1,
name: 'Tom Nook',
orders:[{id: 1, desc: 'pencil'}]
},
{...}
]
{% include code-caption.html content="Node.js API" %}
await customerRepository.find({
include: ['orders', 'address'],
});
{% include code-caption.html content="REST" %}
/customers?filter[include][]=orders&filter[include][]=address
Result:
[{
id: 1,
name: 'Tom Nook',
orders:[{id: 1, desc: 'pencil'}],
address: {'8200 Warden Ave'}
},
{...}
]
{% include code-caption.html content="Node.js API" %}
await customerRepository.find({
include: [
{
relation: 'orders',
scope: {
include: [{relation: 'shipment'}],
},
},
],
});
{% include code-caption.html content="REST" %}
(using encodeURIComponent)
/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:
[{
id: 1,
name: 'Tom Nook',
orders:[
{id: 123,
desc: 'pencil',
shipment: {id: 999, company: 'UPS'} // nested related models
}
],
},
{...}
]
fields and include for a belongsTo relationIf 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:
await postRepository.find({
include: [{relation: 'category'}],
fields: ['title', 'categoryId'],
});
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):
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:
await postRepository.findById('123', {
include: [
{
relation: 'owner',
scope: {
// fetch 1st "page" with 5 entries in it
skip: 0,
limit: 5,
},
},
],
});
{% include important.html content="The limit filter will be applied on a per parent record basis. So each parent record will include a max of limit number of records.
Previously, we had a bug where limit will be applied globally, so not all parent's records will include related objects depending on the limit value.
To keep backward compatibility with this, in the weird case it is needed, you can use totalLimit instead. For more details see here
" %}
In the Node.js API, you can simply access the returned model instance with related items as a plain JSON object. For example:
const result = await postRepository.find({
include: [{relation: 'owner'}, {relation: 'orders'}],
});
console.log(result[0].owner, result[0].orders);
// log the related owner and order of the first returned instance
Note the relation properties such as post.owner reference a JavaScript
function for the relation method.
These examples assume a customer model with a hasMany relationship to a reviews model.
Return all customers including their reviews:
/customers?filter[include][]=reviews
Return all customers including their reviews and also their orders:
/customers?filter[include][]=reviews&filter[include][]=orders
Return all customers whose age is 21, including their reviews:
/customers?filter[include][]=reviews&filter[where][age]=21
Return first two customers including their reviews:
/customers?filter[include][]=reviews&filter[limit]=2
See also: Querying related models.