I get the below error message on a GraphQL query to Contentful, but do not understand why.
Error message:
"Query cannot be executed. The maximum allowed complexity for a query
is 11000 but it was 12100. Simplify the query e.g. by setting lower
limits for collections."
Query:
query ClassCollection(
$slug: String
$limit: Int
) {
classCollection(
where: { slug: $slug }
limit: $limit
) {
items {
slug
title
linkedFrom {
courseCollection {
items {
slug
}
}
}
filesCollection {
items {
title
asset {
title
fileName
url
width
height
contentType
}
}
}
}
}
}
Content model:
- Course
- A course contains a reference field pointing to one or more classes
- This is restricted to MAX 10 classes, in the content model
- Class
- A class contains a reference field pointing to one or more files
- This is restricted to MAX 10 files, in the content model
Notes
- Given the restrictions set in Contentful, the queries should not be very deep / complex.
- I only have a few entries in Contentful
Question
Why am I getting that error message and how can I fix it?
What I tried
- I can limit the number of query results, but that is not solving the underlying problem. In any case, the query becomes too complex already at a limit of 50 or so. Which is way too little.
- Since I am trying to figure out what course each class comes from, I could just pull all the courses and all the classes (which is not too complex), and then do a quick array filter in JavaScript based on slugs. However, it would be much nicer to do it directly in the query. Here is a link showing Contentful recommending the linkedFrom field for this purpose.
EDIT: Calculating the Query Complexity
- For the sake of the calculation, let's assume we limit the number of classes, via the query, to 100. So, 100 classes maximum.
- Then, since each course can contain a maximum of 10 classes, the maximum number of courses that could be returned is 1,000. I am not sure about this one actually. It has to look at each course, and find the class, which should be 1,000 lookups max.
- Each class can only have 10 files at most, giving us a complexity of 1,000 here as well.
- That is a maximum complexity of 2,100. I am obviously wrong, since the error message says the complexity is 12,100. Any idea what I am missing?
EDIT 2
- I checked the x-contentful-graphql-query-cost header in DevTools, and the cost without requesting the filesCollection is 10,100.
- With the filesCollection, but without the linkedFrom field, it is 2,100.
- Thus, the problem is clearly with the linkedFrom field.
- I am currently thinking that since classes return up to 100 entries, and since the default number of entries in Contentful is 100, the reverse look-up that linkedFrom probably has to do, checks 100 class entries for each of the 100 courses. Thus ending up at 100 * 100 = 10,000 complexity.
Conclusion
- Unless someone has a better idea, I will conclude that it is in fact better to do the connecting of classes to courses in JavaScript, after the data has been pulled. That way we only work on a limited set, not the worst case scenario of 100 * 100.
Even if Contentful's GraphQL API is aware of the validation limits for how many Classes in a Course in the linkedFrom
field, it is feasible that any other content type in your space that has reference fields may (in theory) also link to a Class, so the query must assume that there can be up to the set limit of linkedFrom
entries that aren't Courses.
So your (default) complexity in the query you've shared is:
- 100
classes
- 100*100
linkedFrom
entries
- 100*10
files
- 100*10
asset
fields (ie, 1 per file
)
- = 12,100
It may be possible that enforcing validation on ALL reference fields throughout your space to exclude Classes is reflected in the GraphQL response, altho unlikely.
Alternative approaches could be to
- Limit the query only to classes that are linked from the course reference field (eg something like
(where: { linkedFrom: 'courseCollection'})
), which might be aware of the validation restriction.
- Split the query into presentational and relational content - either by requesting the two parts of the Class (
files
and linkedFrom
) separately, or getting the class and file data first and then querying for courses that have that class in their classes field.