Using nestedFields to Query Related Entries
Liferay 7.4 U69+/GA69+
The nestedFields
parameter causes Liferay to return multiple levels of related object entries in a single GET request. Pass the nestedFields
parameter with the relationship names to include in the query, separating each relationship with a comma: nestedFields=[firstObjectRelationship],[secondObjectRelationship]
. If the relationships span multiple levels, set the nestedFieldsDepth
parameter to the depth you need. You can include up to five levels (e.g., nestedFieldsDepth=5
).
The nestedFields
parameter optimizes your request by retrieving entries with related entries that would otherwise require multiple requests. To return only the related entries, Liferay provides dedicated relationship APIs. See Using Relationship REST APIs for an introduction.
To proceed, set up a new Liferay 7.4 instance and prepare the provided tutorial code. Then run the scripts to create related entries and query them using the nestedFields
parameter.
Currently, access to nested fields or relationships is currently unavailable when using a custom object on the “many” side of a one-to-many relationship with a system object. Keep this in mind when planning how to retrieve your data.
Setting Up a Liferay Instance
Start a new Liferay instance by running
docker run -it -m 8g -p 8080:8080 liferay/portal:7.4.3.112-ga112
Sign in to Liferay at http://localhost:8080. Use the email address test@liferay.com and the password test. When prompted, change the password to learn.
Next, create and relate three object definitions.
Creating Related Object Definitions
-
Open the Global Menu (), go to the Control Panel tab, and click Objects.
-
Create three object drafts.
First Object:
Field Value Label Able
Plural Label Ables
Name Able
Second Object:
Field Value Label Baker
Plural Label Bakers
Name Baker
Third Object:
Field Value Label Charlie
Plural Label Charlies
Name Charlie
-
Add the
name
text field to each object draft.Label Field Name Type Required Name
name
Text ✔ -
Define the following relationships.
For Able:
Label Relationship Name Type Object Able to Baker
ableToBaker
One to Many Baker For Baker:
Label Relationship Name Type Object Baker to Charlie
bakerToCharlie
One to Many Charlie For Charlie:
Label Relationship Name Type Object Charlie to Able
charlieToAble
Many to Many Able -
Publish each object.
Once published, you can access each object via Headless APIs.
Preparing the Sample Code
Run the commands below to download and unzip the provided sample code:
curl https://resources.learn.liferay.com/dxp/latest/en/building-applications/objects/understanding-object-integrations/using-custom-object-apis/liferay-w4s7.zip -O
unzip liferay-w4s7.zip
The ZIP provides shell scripts that run cURL commands for creating, relating, and querying object entries using REST APIs. This includes two GET commands for querying related entries.
For a complete list of APIs generated for site and company objects, see Objects Headless Framework Integration. You can view and test custom object APIs via the Liferay API Explorer at [server]:[port]/o/api
(e.g., localhost:8080/o/api
). Click REST Applications and select an API.
Creating and Querying Related Object Entries
-
Navigate to the
curl
folder in theliferay-w4s7
project.cd liferay-w4s7/curl
-
Execute
Able_POST_ToCompany
to create Able entries../Able_POST_ToCompany.sh
Copy the first entry’s ID for use with the following POST command.
{ ... "externalReferenceCode" : "able-one", "id" : 47512, ... "name" : "Able 1" } { ... "externalReferenceCode" : "able-two", "id" : 47514, ... "name" : "Able 2" } { ... "externalReferenceCode" : "able-three", "id" : 47516, ... "name" : "Able 3" }
-
Execute
Baker_POST_ToCompany
using the ID forable-one
as a parameter../Baker_POST_ToCompany.sh [ableId]
This creates three Baker entries and relates them to the specified Able entry using the
ableToBaker
relationship.Each Baker entry has three
ableToBaker
relationship fields:ableToBakerERC
,r_ableToBaker_c_ableId
, andr_ableToBaker_c_ableERC
.{ ... "externalReferenceCode" : "baker-one", "id" : 47518, ... "name" : "Baker 1", "ableToBakerERC" : "able-one", "r_ableToBaker_c_ableId" : 47512, "r_ableToBaker_c_ableERC" : "able-one" } { ... "externalReferenceCode" : "baker-two", "id" : 47520, ... "name" : "Baker 2", "ableToBakerERC" : "able-one", "r_ableToBaker_c_ableId" : 47512, "r_ableToBaker_c_ableERC" : "able-one" } { ... "externalReferenceCode" : "baker-three", "id" : 47522, ... "name" : "Baker 3", "ableToBakerERC" : "able-one", "r_ableToBaker_c_ableId" : 47512, "r_ableToBaker_c_ableERC" : "able-one" }
Copy the first Baker entry ID for use with the following POST command.
-
Execute
Charlie_POST_ToCompany
using the ID forbaker-one
as a parameter../Charlie_POST_ToCompany.sh [bakerId]
This creates three Charlie entries and relates them to the specified Baker entry using the
bakerToCharlie
relationship.{ ... "externalReferenceCode" : "charlie-one", "id" : 47524, ... "r_bakerToCharlie_c_bakerERC" : "baker-one", "bakerToCharlieERC" : "baker-one", "name" : "Charlie 1", "r_bakerToCharlie_c_bakerId" : 47518 } { ... "externalReferenceCode" : "charlie-two", "id" : 47526, ... "r_bakerToCharlie_c_bakerERC" : "baker-one", "bakerToCharlieERC" : "baker-one", "name" : "Charlie 2", "r_bakerToCharlie_c_bakerId" : 47518 } { ... "externalReferenceCode" : "charlie-three", "id" : 47528, ... "r_bakerToCharlie_c_bakerERC" : "baker-one", "bakerToCharlieERC" : "baker-one", "name" : "Charlie 3", "r_bakerToCharlie_c_bakerId" : 47518 }
You now have three Charlie entries related to a Baker entry that is itself related to an Able entry. However, if you query a Charlie entry using a basic GET request, the response only includes details for the Charlie entry. It does not include details for the related Baker or Able entries. To return details for these entries, you must use the
nestedFields
andnestedFieldsDepth
parameters.Copy the first entry’s ID for use with the following GET command.
-
Execute
Charlie_GET_ById
using a Charlie entry ID as a parameter../Charlie_GET_ById.sh [charlieId]
This GET request calls an
o/c/charlies
endpoint with thenestedFields
andnestedFieldsDepth
parameters.
curl \
"http://localhost:8080/o/c/charlies/${1}/?nestedFields=ableToBaker,bakerToCharlie&nestedFieldsDepth=2" \
--user "test@liferay.com:learn"
nestedFields
: Determines the relationship(s) to include in the query (ableToBaker,bakerToCharlie
).
nestedFieldsDepth
: Determines the depth of entries to include (2
).
This command returns all three levels of related objects (i.e., Charlie, Baker, and Able).
{
...
"externalReferenceCode" : "charlie-one",
"id" : 47524,
...
"r_bakerToCharlie_c_baker" : {
...
"externalReferenceCode" : "baker-one",
"id" : 47518,
...
"r_ableToBaker_c_able" : {
...
"externalReferenceCode" : "able-one",
"id" : 47512,
...
"name" : "Able 1"
},
"bakerToCharlie" : [ {
...
"externalReferenceCode" : "charlie-one",
"id" : 47524,
...
"r_bakerToCharlie_c_bakerERC" : "baker-one",
"bakerToCharlieERC" : "baker-one",
"name" : "Charlie 1",
"r_bakerToCharlie_c_bakerId" : 47518
}, {
...
"externalReferenceCode" : "charlie-two",
"id" : 47526,
...
"r_bakerToCharlie_c_bakerERC" : "baker-one",
"bakerToCharlieERC" : "baker-one",
"name" : "Charlie 2",
"r_bakerToCharlie_c_bakerId" : 47518
}, {
...
"externalReferenceCode" : "charlie-three",
"id" : 47528,
...
"r_bakerToCharlie_c_bakerERC" : "baker-one",
"bakerToCharlieERC" : "baker-one",
"name" : "Charlie 3",
"r_bakerToCharlie_c_bakerId" : 47518
} ],
"name" : "Baker 1",
"ableToBaker" : {
...
"externalReferenceCode" : "able-one",
"id" : 47512,
...
"name" : "Able 1"
},
"r_ableToBaker_c_ableId" : 47512,
"r_ableToBaker_c_ableERC" : "able-one"
},
"r_bakerToCharlie_c_bakerERC" : "baker-one",
"bakerToCharlie" : {
...
"externalReferenceCode" : "baker-one",
"id" : 47518,
...
"r_ableToBaker_c_able" : {
...
"externalReferenceCode" : "able-one",
"id" : 47512,
...
"name" : "Able 1"
},
"bakerToCharlie" : [ {
...
"externalReferenceCode" : "charlie-one",
"id" : 47524,
...
"r_bakerToCharlie_c_bakerERC" : "baker-one",
"bakerToCharlieERC" : "baker-one",
"name" : "Charlie 1",
"r_bakerToCharlie_c_bakerId" : 47518
}, {
...
"externalReferenceCode" : "charlie-two",
"id" : 47526,
...
"r_bakerToCharlie_c_bakerERC" : "baker-one",
"bakerToCharlieERC" : "baker-one",
"name" : "Charlie 2",
"r_bakerToCharlie_c_bakerId" : 47518
}, {
...
"externalReferenceCode" : "charlie-three",
"id" : 47528,
...
"r_bakerToCharlie_c_bakerERC" : "baker-one",
"bakerToCharlieERC" : "baker-one",
"name" : "Charlie 3",
"r_bakerToCharlie_c_bakerId" : 47518
} ],
"name" : "Baker 1",
"ableToBaker" : {
...
"externalReferenceCode" : "able-one",
"id" : 47512,
...
"name" : "Able 1"
},
"r_ableToBaker_c_ableId" : 47512,
"r_ableToBaker_c_ableERC" : "able-one"
},
"name" : "Charlie 1",
"r_bakerToCharlie_c_bakerId" : 47518
}
-
Execute
Charlie_PUT_CharlieToAble_ByExternalReferenceCode
with these ERCs../Charlie_PUT_CharlieToAble_ByExternalReferenceCode.sh charlie-one charlie-two charlie-three able-one
This relates all three Charlie entries directly with the specified
able-one
entry using thecharlieToAble
relationship. -
Execute
Able_GET_ByExternalReferenceCode
with the Able entry’s ERC../Able_GET_ByExternalReferenceCode.sh able-one
This GET request calls an
o/c/ables
endpoint with thenestedFields
parameter.
curl \
"http://localhost:8080/o/c/ables/by-external-reference-code/${1}?nestedFields=charlieToAble" \
--user "test@liferay.com:learn"
nestedFields
: Determines the relationship(s) to include in the query (charlieToAble
).
This command returns details for able-one
along with all details for the three related Charlie entries.
{
...
"externalReferenceCode" : "able-one",
"id" : 47512,
...
"charlieToAble" : [ {
...
"externalReferenceCode" : "charlie-one",
"id" : 47524,
...
"r_bakerToCharlie_c_bakerERC" : "baker-one",
"bakerToCharlieERC" : "baker-one",
"name" : "Charlie 1",
"r_bakerToCharlie_c_bakerId" : 47518
}, {
...
"externalReferenceCode" : "charlie-two",
"id" : 47526,
...
"r_bakerToCharlie_c_bakerERC" : "baker-one",
"bakerToCharlieERC" : "baker-one",
"name" : "Charlie 2",
"r_bakerToCharlie_c_bakerId" : 47518
}, {
...
"externalReferenceCode" : "charlie-three",
"id" : 47528,
...
"r_bakerToCharlie_c_bakerERC" : "baker-one",
"bakerToCharlieERC" : "baker-one",
"name" : "Charlie 3",
"r_bakerToCharlie_c_bakerId" : 47518
} ],
"name" : "Able 1"
}
Charlie_GET_ById.sh
curl \
"http://localhost:8080/o/c/charlies/${1}/?nestedFields=ableToBaker,bakerToCharlie&nestedFieldsDepth=2" \
--user "test@liferay.com:learn"
Able_GET_ByExternalReferenceCode.sh
curl \
"http://localhost:8080/o/c/ables/by-external-reference-code/${1}?nestedFields=charlieToAble" \
--user "test@liferay.com:learn"