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.
Important:
You can use an include filter with find(),
findOne()
and findById()
methods.
Node.js API
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:
- relationName is the name of a relation defined in repositories. Check Relations for details.
REST API
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.
Scope Filter
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>
Examples
- Return all customers with their orders:
await customerRepository.find({include: ['orders']});
/customers?filter[include][]=orders
Or stringified JSON format:
/customers?filter={"include":["orders"]}
Result:
[{
id: 1,
name: 'Tom Nook',
orders:[{id: 1, desc: 'pencil'}]
},
{...}
]
- Return all customers with their orders and their address:
await customerRepository.find({
include: ['orders', 'address'],
});
/customers?filter[include][]=orders&filter[include][]=address
Result:
[{
id: 1,
name: 'Tom Nook',
orders:[{id: 1, desc: 'pencil'}],
address: {'8200 Warden Ave'}
},
{...}
]
- Return all customers with their orders and also the shipment information of orders:
await customerRepository.find({
include: [
{
relation: 'orders',
scope: {
include: [{relation: 'shipment'}],
},
},
],
});
(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
}
],
},
{...}
]
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
:
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.
Note:
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,
},
},
],
});
Important:
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
Access included objects
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.
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][]=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.