Content Delivery API > Direct vs. Inverse relationships

Direct vs. Inverse relationships

Link fields allow you to define relationships between records — e.g., a "blog post" record can reference a "person" record through an "author" link field.

Using the Content Delivery API, it is possible to follow such links between records in both directions. Continuing with our example:

  • Starting from a blog post, get its author (that's the direct relationship expressed by the link field in the blog post record).

  • Starting from a person, get all their blog posts (that's the inverse relationship, automatically derived by looking at the value of the author field in every blog post).

Following a direct relationship

It is trivial to fetch information about a record that's directly referenced through a link field: just use the ID of the field like you would with any other:

query {
allBlogPosts {
title
author {
id
firstName
lastName
}
}
}

Following an inverse relationship

If you're interested in the collection of records that are referencing a specific record of your interest, first you need to enable the "Enable inverse relationships fields in GraphQL?" option in the model settings — in our example, the "person" model:

Once the option is enabled, you will be able to perform inverse relationship queries using the _allReferencingXXX GraphQL field:

query {
allPeople {
id
name
_allReferencingBlogPosts {
id
title
}
}
}
Inverse relationship queries are blocks-aware!

Inverse relationship queries will also return results for links present inside some blocks embedded in the record, no matter the depth.

Pagination

With no arguments, the result will be the first 20 referencing records, but just like with regular collection queries, you can paginate your results, and get the total number of records with the _allReferencingXXXMeta field:

query {
allPeople {
_allReferencingBlogPosts(first: 5, skip: 10) {
...
}
_allReferencingBlogPostsMeta {
count
}
}
}

Filtering references by field

Suppose that our blog post model has two different link fields that point to the same "person" model: the author and the reviewer.

If you're interested in only getting blog posts that link to a person via a specific field (e.g., the reviewer field), you can use the through: { fields: } argument:

query {
allPeople {
_allReferencingBlogPosts(through: {fields: {anyIn: [blogPost_reviewer]}}) {
id
title
}
}
}

With the through: { fields: } argument is also possible to get only references coming from fields defined inside the record blocks embedded in a record via Modular Content or Structured Text fields.

As an example, the following inverse relationship query:

query {
allPeople {
_allReferencingDocPages(
through: {fields: {anyIn: [docPage_main__chapter_author]}}
) { ... }
}
}

Will only return documentation pages which link to a specific author through the author link of the blocks of type chapter defined inside the main field of the page itself.

Use the API Explorer to make it easier to write your queries!

As you can see from the last example, arguments like docPage_main__chapter_author can be tricky to write, and the situation can get much worse when you start considering nested blocks!

Always remember that in GraphQL you can harness the powers of introspection and use the API Explorer in your project to get query intelligent code-completion.

Filtering references by locale

Suppose that the "author" link in our blog post model is localized, so depending on the locale, the author of the blog post will be a different record.

To filter references in a specific set of locales, ignoring the others, you can use the through: { locales: } argument:

query {
allPeople {
_allReferencingBlogPosts(through: {locales: {anyIn: [en]}}) {
id
title
}
}
}

Likewise, if you need to filter references that are coming from non-localized fields, you can use the _nonLocalized enum value:

query {
allPeople {
_allReferencingBlogPosts(through: {locales: {anyIn: [_nonLocalized]}}) {
id
title
}
}
}

Ordering

To retrieve references in a specific order, you can use the orderBy argument. Suppose the "blog post" model has a title string field, you can specify the order like this:

query {
allPeople {
_allReferencingBlogPosts(orderBy: title_ASC) {
id
title
}
}
}

Deep filtering

You can even filter references based on one or more of its fields:

query {
allPeople {
_allReferencingBlogPosts(filter: {name: {matches: {pattern: "trip"}}}) {
id
title
}
}
}