The flat content structure adopted by Contentful is perfect for eliminating repetitive work out of the process creation. An entry containing generic information - be it a legal disclaimer, author bio or shop opening hours - can be re-used over and over again by simply attaching them to a reference field.
As a result, a sizeable share of content models created by our users combine several simpler content types into a more complex entry powering a website page or an app module. Imagine you were to recreate an IMDB website on Contentful, your film entry would almost certainly reference content types describing a movie genre, cast, and critic reviews.
Adding a new movie to the project setup this way is bliss: it's quick, flexible, and stays up to date, no matter how many new movies Danny "Machete" Trejo churns out in a given year. It's the querying part where you are likely to run into trouble.
Let's assume for a second that you were overcome with curiosity and wanted to count how many movie credits Mr. Trejo earned to date. The right way to go about it would be to fetch all the films that feature Danny Trejo as an actor. Alas, until now there was no easy way to do it because the Content Delivery API (CDA) did not allow you to filter entries by values of their reference fields.
Developers got around this limitation in two ways: some reverted to doing a double lookup: first, query the content type Actors to obtain an entry ID for Danny Trejo. Then use the returned value to query the content type Movies to select the right movies. Here is how this approach looks in practice:
1 2 3 4 5 6 7
https://cdn.contentful.com/space/space-id/entries ?content_type=actors &fields.name[all]=Trejo,Danny https://cdn.contentful.com/space/space-id/entries ?content_type=movies &fields.actors.sys.id[in]=someID
Others would load all entries in memory and proceed to manipulate entries on the fly, making their ops team wince with pain in the process. While both approaches eventually got you where you needed to go, they are cumbersome and - when used with big data sets (Mr. Trejo has solid 324 credits to his name) - run the risk of hitting the URI limit or hogging up all the available memory.
We thought this problem deserves our attention and so we worked on modifying the behavior of our APIs to accommodate the use of filtered reference values. Hence, from now on, you would be to achieve all Danny Trejo's movie credits in a single API call. Let's look at the query above, implemented with a new syntax:
1 2 3 4
https://cdn.contentful.com/spaces/my-space-id/entries/ ?content_type=movies &fields.actors.sys.contentType.sys.id=actors &fields.actors.fields.name[all]=Trejo,Danny
It feels very intuitive, doesn't it? And you can take it one step further by using multiple values to filter only Danny Trejo movies which were also directed by Quentin Tarantino, or movies with Danny Trejo that received a rating of 6 stars or higher. Here is how those queries would look like:
1 2 3 4 5 6
https://cdn.contentful.com/spaces/my-space-id/entries/ ?content_type=movies &fields.actors.sys.contentType.sys.id=actors &fields.actors.fields.name[all]=Trejo,Danny &fields.directors.sys.contentType.sys.id=director &fields.directors.fields.name[all]=Tarantino, Quentin
1 2 3 4 5 6
https://cdn.contentful.com/spaces/my-space-id/entries/ ?content_type=movies &fields.actors.sys.contentType.sys.id=actors &fields.actors.fields.name[all]=Trejo,Danny &fields.reviews.sys.contentType.sys.id=review &fields.reviews.fields.rating[gte]=6
Going further, you could combine reference search with the previously introduced 'select' operator to streamline the type of information you get in the response.
Search on reference field values is supported by all our APIs (Content Management, Content Delivery, and Content Preview) and it's coming to the supported SDKs in the near future. In case you wanted to run complex queries in the Contentful Web App, we are considering this move, but at the moment cannot provide a firm timeline.
Before you go, a word of caution - search on reference fields only works with entries, that is you cannot search assets the same way, and you can only search one level deep. To ensure smooth performance, we also limit the number of searcheable reference fields to two.