Was this page helpful?

Filter API results with relational queries

Imagine a scenario of recreating an IMDB website on Contentful. In this setup, every film entry would refer to content types describing a movie genre, cast, production house, and ratings. If a user needs to know how many movies are thrillers, the ideal way to go about it would be to fetch all the films that have genre as 'Thriller'.

Previously, there was no easy way to do it because the Content Delivery API (CDA) did not allow filtering of entries by values of their reference fields.

To address this problem, Contentful has introduced a new filtering capability to the APIs, enabling the user to query for content based on the fields of referenced entries. The following query explains how to get all the thriller movie credits in a single API call:

https://cdn.contentful.com/spaces/my-space-id/entries/
    ?content_type=movies
    &fields.genre.sys.contentType.sys.id=genre
    &fields.genre.fields.label[all]=Thriller

It can be extended one step further, by using multiple values to filter only thriller movies which were made under the banner of Universal Studios.

https://cdn.contentful.com/spaces/my-space-id/entries/
    ?content_type=movies
    &fields.genre.sys.contentType.sys.id=genre
    &fields.genre.fields.label[all]=Thriller
    &fields.productionhouse.sys.contentType.sys.id=productionhouse
    &fields.productionhouse.fields.name[all]=Universal Studios

The reference can also be combined with the select operator to streamline the type of information required in the response.

It is important to understand that search on reference fields only works with entries. It cannot search assets the same way, and the search can only be one level deep. To ensure consistent performance, the number of searchable reference fields is limited to two.

Search on reference field values is supported by all the REST APIs (Content Management, Content Delivery, and Content Preview) and all the client libraries.

Relational filtering with the GraphQL Content API

Using the GraphQL Content API, you can query for any linked entry (single reference field) or any Array (many reference field) if you have a validation rule on that makes them only accept a single content type.

Consider the following content model:

Relational filtering diagram

query HumansQuery {
  peopleCollection(
    limit: 10
    where:{
      restaurants: {name_contains: "Steves Place"},
      manager: {name_contains: "Charlotte"}
    }
  ) {
    items {
      manager {
        name
      }
      name
      restaurantsCollection(
        limit: 10,
        where: {
          menus: {
            name_contains: "Drinks"
          }
        }
      ) {
        items {
          menusCollection(
            limit: 3
            where: {
              menuItems: {
                name_in: ["Chicken Stew", "Sirloin Steak", "Lamb Burger", "Fanta", "Orange Juice"]
              }
            }
          ) {
            items {
              name
              menuItemsCollection(
                limit: 5,
                where:{name:"Today's special"}
              ) {
                items {
                  name
                }
              }
            }
          }
        }
      }
    }
  }
}

The query returns the following values:

  • All of the people where their manager's name contains “Charlotte“ and they have a restaurant(s) with a name that contains “Steves Place”.

  • From the list of restaurants it only returns the ones that reference a Menu with a name that contains “Drinks”.

  • For the menus list we have only return the menus that have menu items with a name from this list ["Chicken Stew", "Sirloin Steak", "Lamb Burger", "Fanta", "Orange Juice"]

  • For the menu items list only return the items with the name equal to Today's special.

NOTE: You must have a validation on the reference field to make it only accept a single content type. Otherwise, the query will not work.