> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://contentful.com/developers/docs/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://contentful.com/_mcp/server. # Collection filters The GraphQL Content API allows users to specify filters on root collection queries. Collections could be filtered by different fields or combination of fields that contain collection items. There are general and type specific filters: | Filter | Postfix | Field type | | ----------------- | ------------------- | -------------------- | | equal | *(none)* | `` | | not equal | `_not` | `` | | exists | `_exists` | `` | | contains | `_contains` | String, RichText | | does not contain | `_not_contains` | String, RichText | | greater than | `_gt` | Number, Date | | greater or equals | `_gte` | Number, Date | | less than | `_lt` | Number, Date | | less or equals | `_lte` | Number, Date | | in given list | `_in` | String, Number, Date | | not in given list | `_not_in` | String, Number, Date | | within circle | `_within_circle` | Location | | within rectangle | `_within_rectangle` | Location | | contains all | `_contains_all` | Array | | contains some | `_contains_some` | Array | | contains none | `_contains_none` | Array | For each content type the schema defines an input type to filter entries of that content type. For example, for the type `FriendlyUser` structured in the following way: ```graphql type FriendlyUser { sys: Sys name: String age: Integer } ``` The schema defines the following filter input type: ```graphql input FriendlyUserFilter { sys: SysFilter contentfulMetadata: ContentfulMetadataFilter name: String name_not: String name_exists: Boolean name_contains: String # ... more name filters age: Number age_gt: Number age_lt: Number # ... more age filters AND: [FriendlyUserFilter] OR: [FriendlyUserFilter] } ``` Filter inputs can be passed to collection queries of their corresponding type to filter out mutations and the result set. For example, to find all `FriendlyUser`s whose name is "Frank" or "Francine" and who are older than 30 years, write the following query: ```graphql query { friendlyUserCollection(where: { AND: [ { OR: [ { name: "Frank" }, { name: "Francine" } ] }, { age_gt: 30 } ], }) { name age } } ``` ## Limitations It is not possible to filter on fields of type `Object` or `RichText`. There's an exemption in the case of the `ContentfulMetadata` type. `_contains` filter is case insensitive and must be at least 2 characters long to work. The `_contains` filter is analogous to the `[match]` filter in the *REST API* content. Check the [documentation](/references/content-delivery-api/full-text-search-on-a-field) of the `[match]` operator for more information about the details of full-text search in contentful. For performance reasons it is not recommended to use the `_contains` filter when searching for slugs or text IDs. Please use the equality search instead. ## Filter generation Filter input types are derived from the content model, just like the output types. For each content type, one filter input type is derived. The user can pass it to the corresponding root collection query. Each filter input type has the `sys`, `AND`, and `OR` fields as well as additional field type-specific filters for every field. Name of the filter input type is derived from the output type by appending `Filter` to it. ## Logical connectives Each filter input type has two special fields `AND` and `OR` used to logically combine filters. If multiple fields are specified on a filter, they get connected with an implicit `AND`: ```graphql query { friendlyUserCollection(where: { OR: [ { name: "Hans" }, { name: "Joe" } ] age_gte: 30, age_lte: 40 }) { name } } ``` And result in the following equivalent query: ```graphql query { friendlyUserCollection(where: { AND: [ OR: [ { name: "Hans" }, { name: "Joe" } ], { age_gte: 30 }, { age_lte: 40 } ] }) { name } } ``` Both queries return all the friendly users between the age of 30 to 40 and are named either Hans or Joe. ## Filters by field type For each field in a content type a set of filter fields is added to the content type's filter input type. The type of filters is determined by the [field type](/concepts/data-model#fields). ### `Symbol` and `Text` GraphQL Content API does not distinguish between `Symbol` and `Text` types and generates the same filters for both. For example, if the content type `FriendlyUser` has a `Symbol` field `name`, the following types are generated: ```graphql type FriendlyUser { # ... other fields name: String } input FriendlyUserFilter { # ... other field filters # Matches if the field is equal to the given value name: String # Matches if the field is not equal to the given value name_not: String # Matches if the field exists name_exists: Boolean # Matches if the field value equal one of the given values name_in: [String] # Matches if the field value does not equal any of the given values name_not_in: [String] # Matches if given value is a substring of the field value name_contains: String # Matches if given value is not a substring of the field value name_not_contains: String } ``` ### `Number` and `Integer` Filter names for `Integer` and `Number` types are the same. They only differ in the input types for values. For `Integer` fields the value type is `Int`, whereas for `Number` fields the type is `Float`. For example, if the content type `FriendlyUser` has an `Integer` field `age`, the following types are generated: ```graphql type FriendlyUser { # ... other fields age: Int } input FriendlyUserFilter { # ... other field filters # Matches if the field is equal to the given value age: Int # Matches if the field is not equal to the given value age_not: Int # Matches if the field exists age_exists: Boolean # Matches if the field value equal one of the given values age_in: [Int] # Matches if the field value does not equal any of the given values age_not_in: [Int] # Matches if the field value is strictly smaller than the given value age_lt: Int # Matches if the field value is smaller than or equal to the given value age_lte: Int # Matches if the field value is strictly greater than the given value age_gt: Int # Matches if the field value is greater than or equal to the given value age_gte: Int } ``` ### `Boolean` `Boolean` filter accepts values of type `Boolean` and can only be used on fields with type `Boolean`. For example, if the content type `FriendlyUser` has a `Boolean` field `employed`, the following types are generated: ```graphql type FriendlyUser { # ... other fields employed: Boolean } input FriendlyUserFilter { # ... other field filters # Matches if the field is equal to the given value employed: Boolean # Matches if the field is not equal to the given value employed_not: Boolean # Matches if the field exists employed_exists: Boolean } ``` ### `Date` For fields with type `Date` the value types are `DateTime`. The value for filter should be provided as a full DateTime value in ISO-8601 format (e.g. `yyyy-mm-ddThh:mm:ss:sssZ`). For example, if the content type `FriendlyUser` has a `DateTime` field `birthday`, the following types are generated: ```graphql type FriendlyUser { # ... other fields birthday: DateTime } input FriendlyUserFilter { # ... other field filters # Matches if the field is equal to the given value birthday: DateTime # Matches if the field is not equal to the given value birthday_not: DateTime # Matches if the field exists birthday_exists: Boolean # Matches if the field value equal one of the given values birthday_in: [DateTime] # Matches if the field value does not equal any of the given values birthday_not_in: [DateTime] # Matches if the field value is strictly smaller than the given value birthday_lt: DateTime # Matches if the field value is smaller than or equal to the given value birthday_lte: DateTime # Matches if the field value is strictly greater than the given value birthday_gt: DateTime # Matches if the field value is greater than or equal to the given value birthday_gte: DateTime } ``` ### `Location` For fields with type `Location` the value types are either `Circle` or `Rectangle`. The `Circle` scalar type has the following format: ```javascript { lat: 10.11, lon: 10.11, radius: 10, } ``` where `lat` and `lon` are coordinates of the center of the circle and `radius` its radius in kilometers. The `Rectangle` scalar type has the following format: ```javascript { topLeftLat: 40, topLeftLon: 13.35, bottomRightLat: 41, bottomRightLon: 14.36 } ``` where `topLeftLat` with `topLeftLon` are the coordinates of the top left corner of the rectangle, and `bottomRightLat` with `bottomRightLon` are the coordinates of the bottom right corner of the rectangle. For example, if the content type `FriendlyUser` has a `Location` field `place`, the following types are generated: ```graphql type FriendlyUser { # ... other fields place: Location } input FriendlyUserFilter { # ... other field filters # Matches if the position is inside the given circle place_within_circle: Circle # Matches if the position is inside the given rectangle place_within_rectangle: Rectangle } ``` ### `Array` For Array fields with the value type String. The value for the filter should be an array of string values. For example, if the content type `FriendlyUser` has an `Array` field `nicknames`, the following types are generated: ```graphql type FriendlyUser { # ... other fields nicknames: [String] } input FriendlyUserFilter { # ... other field filters # Matches if the field array contains *all* items provided to the filter nicknames_contains_all: [String] # Matches if the field array contains at least one item provided to the filter nicknames_contains_some: [String] # Matches if the field array doesn't contain any item provided to the filter nicknames_contains_none: [String] } ``` ### `Link` For Link fields with a single [`linkContentType`](/references/content-management-api/content-types) validation. Filtering depth is limited to one level of relationships. The collection filter input type has a property corresponding to the field name. The type of this input filter property has filters for all the linked fields (without nested `Link` fields). ```graphql type FriendlyUser { sys: Sys firstbornChild: Child # ... other fields } type Child { name: String } input FriendlyUserFilter { sys: SysFilter contentfulMetadata: ContentfulMetadataFilter firstbornChild: FriendlyUserFirstbornChildFilter # ... more filters } input FriendlyUserFirstbornChildFilter { sys: SysFilter contentfulMetadata: ContentfulMetadataFilter name: String name_not: String name_exists: Boolean name_contains: String # ... more name filters } ``` ### `sys` filters Every filter input type has a `sys` property. The type of the `sys` filter property is the statically defined `SysFilter` type. ```graphql input FriendlyUserFilter { sys: SysFilter # ... other fields } input SysFilter { id: String id_not: String id_in: [String] id_not_in: [String] id_contains: String id_not_contains: String } ``` Similar to other field filters the `SysFilter` input type is generated from the `Sys` output type. For each field in the `Sys` type, a set of corresponding filters are added to `SysFilter`. The following is an example of a query for a list of entries by IDs: ```graphql query { friendlyUserCollection(where: { sys: { id_in: ["id1", "id2"] } }) { sys { id } } } ``` ### `contentfulMetadata` filters Every filter input type has a `contentfulMetadata` property. The type of the `contentfulMetadata` filter property is the statically defined `ContentfulMetadataFilter` type. ```graphql input EntryCollectionFilter { sys: SysFilter contentfulMetadata: ContentfulMetadataFilter } input ContentfulMetadataFilter { tags_exists: Boolean tags: ContentfulMetadataTagsFilter } input ContentfulMetadataTagsFilter { id_contains_some: [String!] id_contains_none: [String!] id_contains_all: [String!] } ``` The `ContentfulMetadataFilter` input type is generated from the `tags` field in the `ContentfulMetadata` type and its `id` subfield in the `ContentfulTag` type. The following is an example of a query for a list of entries across content types by tag presence and tag IDs: ```graphql query { entryCollection(where: { contentfulMetadata: { tags_exists: true tags: { id_contains_some: ["tagId1", "tagId2"] } } }) { sys { id } contentfulMetadata { tags { id } } } } ``` ## Nested collection filters You can filter a multi reference field collection if the field contains a validation rule that makes it accept only specific content types. If the reference field only accepts a single content type, then you can filter by any field on that content type. ```graphql query { friendlyUserCollection { items { firstName catCollection(where: {name: "foobar"}) { items { name } } } } } ``` On the other hand, if the reference field accepts multiple content types, then you can filter by any field that is common across all of those content types. A field is considered common if it has the same `apiName` (field id) and type on all content types. Consider you have the following content types: * `Cat` * field Name: `Cat Name`, field Id: `name`, type: text * field Name: `Legs`, field Id: `legs`, type: number * field Name: `Lives Left`, field id: `livesLeftOfNine`, type: number * `Dog` * field Name: `Dog Name`, field Id: `name`, type: text * field Name: `Legs`, field Id: `legs`, type: boolean * field Name: `Likes Walks`, field id: `likesWalks`, type: boolean * `Person` * field Name: `Pets`, field Id: `pets`, type: Reference, validations: Accept only specified entry types: Cat, Dog On `Person` you will be able to query `petsCollection` by the fields that have the same field id and type on `Cat` and `Dog`. Per our content types definition above: the only common field is `name` (same field id `name` and type `text` on both collections). The field `legs` will not be a common field as its type differs across the content types. ```graphql query { friendlyUserCollection { items { firstName petsCollection(where: {name: "foobar"}) { items { __typename ... on Cat { name numberOfLivesLeft } ... on Dog { name likesGoingForWalks } } } } } } ``` The `petsCollection` can be filtered by the fields common to both `Cat` and `Dog` types, such as `name`. It cannot be filtered by fields specific to any one content type, such as `livesLeftOfNine` or `likesGoingForWalks`. > **Info** > > **Note:** When you filter a reference field which accepts more than one content type, the complexity of your query increases by the number of content types the field can accept.