Skip to content
On this page

Filter Rules

Permissions, validation, and the API's filter parameter all rely on a specific JSON structure to define their rules. This page describes the syntax for creating flat, relational, or complex filter rules.

Syntax

{
	<field>: {
		<operator>: <value>
	}
}
{
	<field>: {
		<operator>: <value>
	}
}

Examples

json
{
	"title": {
		"_contains": "Directus"
	}
}
{
	"title": {
		"_contains": "Directus"
	}
}
json
{
	"owner": {
		"_eq": "$CURRENT_USER"
	}
}
{
	"owner": {
		"_eq": "$CURRENT_USER"
	}
}
json
{
	"datetime": {
		"_lte": "$NOW"
	}
}
{
	"datetime": {
		"_lte": "$NOW"
	}
}
json
{
	"category": {
		"_null": true
	}
}
{
	"category": {
		"_null": true
	}
}

Filter Operators

Operator Title (in app)OperatorDescription
Equals_eqEqual to
Doesn't equal_neqNot equal to
Less than_ltLess than
Less than or equal to_lteLess than or equal to
Greater than_gtGreater than
Greater than or equal to_gteGreater than or equal to
Is one of_inMatches any of the values
Is not one of_ninDoesn't match any of the values
Is null_nullIs null
Isn't null_nnullIs not null
Contains_containsContains the substring
Contains (case-insensitive)_icontainsContains the case-insensitive substring
Doesn't contain_ncontainsDoesn't contain the substring
Starts with_starts_withStarts with
Starts with_istarts_withStarts with, case-insensitive
Doesn't start with_nstarts_withDoesn't start with
Doesn't start with_nistarts_withDoesn't start with, case-insensitive
Ends with_ends_withEnds with
Ends with_iends_withEnds with, case-insensitive
Doesn't end with_nends_withDoesn't end with
Doesn't end with_niends_withDoesn't end with, case-insensitive
Is between_betweenIs between two values (inclusive)
Isn't between_nbetweenIs not between two values (inclusive)
Is empty_emptyIs empty (null or falsy)
Isn't empty_nemptyIs not empty (null or falsy)
Intersects_intersects [1]Value intersects a given point
Doesn't intersect_nintersects [1]Value does not intersect a given point
Intersects Bounding box_intersects_bbox [1]Value is in a bounding box
Doesn't intersect bounding box_nintersects_bbox [1]Value is not in a bounding box

The following operator has no Title on the Filter Interface as it is only available in validation permissions:

OperatorDescription
_regex [2]Field has to match regex

[1] Only available on Geometry types.
[2] JavaScript "flavor" regex. Make sure to escape backslashes.

Relational

You can target related values by nesting field names. For example, if you have a relational Many-to-One author field, you can set a rule for the author.name field using the following syntax.

json
{
	"author": {
		"name": {
			"_eq": "Rijk van Zanten"
		}
	}
}
{
	"author": {
		"name": {
			"_eq": "Rijk van Zanten"
		}
	}
}

When using M2M relationships, a junction table will be created and the filter applies to the junction table itself. For example, if you have a books collection, with a M2M relationship to authors of each book, the junction collection will probably be named books_authors and have 3 fields : id, books_id and authors_id. To filter specific books depending on their authors you must go through the junction table and the authors_id field :

json
{
	"authors": {
		"authors_id": {
			"name": {
				"_eq": "Rijk van Zanten"
			}
		}
	}
}
{
	"authors": {
		"authors_id": {
			"name": {
				"_eq": "Rijk van Zanten"
			}
		}
	}
}

Logical Operators

You can nest or group multiple rules using the _and or _or logical operators. Each logical operator holds an array of Filter Rules, allowing for more complex filtering. Also note in the example that Logical Operators can be sub-nested into Logical Operators. However, they cannot be sub-nested into Filter Rules.

json
{
	"_or": [
		{
			"_and": [
				{
					"user_created": {
						"_eq": "$CURRENT_USER"
					}
				},
				{
					"status": {
						"_in": ["published", "draft"]
					}
				}
			]
		},
		{
			"_and": [
				{
					"user_created": {
						"_neq": "$CURRENT_USER"
					}
				},
				{
					"status": {
						"_in": ["published"]
					}
				}
			]
		}
	]
}
{
	"_or": [
		{
			"_and": [
				{
					"user_created": {
						"_eq": "$CURRENT_USER"
					}
				},
				{
					"status": {
						"_in": ["published", "draft"]
					}
				}
			]
		},
		{
			"_and": [
				{
					"user_created": {
						"_neq": "$CURRENT_USER"
					}
				},
				{
					"status": {
						"_in": ["published"]
					}
				}
			]
		}
	]
}

Some vs None in One-to-Many

When applying filters to a one-to-many field, Directus will default to a "some" search, for example in:

json
{
	"categories": {
		"name": {
			"_eq": "Recipe"
		}
	}
}
{
	"categories": {
		"name": {
			"_eq": "Recipe"
		}
	}
}

the top level parent will be returned if one of the categories has the name Recipe. This behavior can be overridden by using the explicit _some and _none operators, for example:

json
{
	"categories": {
		"_none": {
			"name": {
				"_eq": "Recipe"
			}
		}
	}
}
{
	"categories": {
		"_none": {
			"name": {
				"_eq": "Recipe"
			}
		}
	}
}

will fetch all parent items that don't have the category "Recipe"

Dynamic Variables

In addition to static values, you can also filter against dynamic values using the following variables.

  • $CURRENT_USER — The primary key of the currently authenticated user
  • $CURRENT_ROLE — The primary key of the role for the currently authenticated user
  • $NOW — The current timestamp
  • $NOW(<adjustment>) - The current timestamp plus/minus a given distance, for example $NOW(-1 year), $NOW(+2 hours)

Functions

You can also use Function Parameters when building Filters.

Nested User / Role variables in Permissions

When configuring permissions, $CURRENT_USER and $CURRENT_ROLE allow you to specify any (nested) field under the current user/role as well as the root ID. For example: $CURRENT_ROLE.name or $CURRENT_USER.avatar.filesize. This includes custom fields that were added to the directus_users/directus_roles tables.

Note: This feature is available for permissions, validation, presets and conditional fields. Regular filters only support the root ID.