Use the $filter query parameter

Microsoft Graph supports the $filter OData query parameter to retrieve a subset of a collection.

The expression specified with $filter is evaluated for each resource in the collection, and only items where the expression evaluates to true are included in the response. Resources for which the expression evaluates to false or to null, or which reference properties that are unavailable due to permissions, are omitted from the response.

The $filter query parameter can also be used to retrieve relationships like members, memberOf, transitiveMembers, and transitiveMemberOf. For example, "get all the security groups that I'm a member of".

Operators and functions supported in $filter expressions

Support for $filter operators varies across Microsoft Graph APIs. The following operators and functions are supported:

Operator type Operator
Equality operators
  • Equals (eq)
  • Not equals (ne)
  • Logical negation (not)
  • In (in)
  • Has (has)
Relational operators
  • Less than (lt)
  • Greater than (gt)
  • Less than or equal to (le)
  • Greater than or equal to (ge)
Lambda operators
  • Any (any)
  • All (all)
Conditional operators
  • And (and)
  • Or (or)
Functions
  • Starts with (startsWith)
  • Ends with (endsWith)
  • Contains (contains)

Note

Support for these operators varies by entity and some properties support $filter only with advanced queries. See the specific resource documentation for details.

Filter using lambda operators

OData defines the any and all operators to evaluate matches on multi-valued properties, that is, either collection of primitive values such as String types or collection of entities.

any operator

The any operator iteratively applies a Boolean expression to each item of a collection and returns true if the expression is true for at least one item of the collection, otherwise it returns false.
The following is the syntax of the any operator:

$filter=collection/any(property:property/subProperty eq 'value-to-match')

Where

  • collection is the property that contains a collection of values or a collection of complex properties.
  • property:property is the range variable that holds the current element of the collection during iteration. This variable can be named almost anything, for example, p:p.
  • subProperty is required when the query applies to a collection of entities. It represents the property of the complex type whose value you're matching against.
  • value-to-match represents the member of the collection against which you're matching.

If you are familiar with C# and LINQ, this would be the equivalent of the above syntax:

collection.Any(property => property.subProperty == "value-to-match")

For example, the imAddresses property of the user resource contains a collection of String primitive types. The following query retrieves only users with an imAddress of admin@contoso.com.

GET https://graph.microsoft.com/v1.0/users?$filter=imAddresses/any(i:i eq 'admin@contoso.com')

The assignedLicenses property of the user resource contains a collection of assignedLicense objects, a complex type with two properties, skuId and disabledPlans. The following query retrieves only users with an assigned license identified by the skuId 184efa21-98c3-4e5d-95ab-d07053a96e67.

GET https://graph.microsoft.com/v1.0/users?$filter=assignedLicenses/any(s:s/skuId eq 184efa21-98c3-4e5d-95ab-d07053a96e67)

To negate the result of the expression inside the any clause, use the not operator, not the ne operator. For example, the following query retrieves only users who aren't assigned the imAddress of admin@contoso.com.

Note: For directory objects like users, the not and ne operators are supported only in advanced queries.

GET https://graph.microsoft.com/v1.0/users?$filter=NOT(imAddresses/any(i:i eq 'admin@contoso.com'))&$count=true
ConsistencyLevel: eventual

all operator

The all operator applies a Boolean expression to each member of a collection and returns true if the expression is true for all the items of the collection, otherwise it returns false. It isn't supported by any property.

Examples using the $filter query operator

The following table shows some examples that use the $filter query parameter. For more information, see the [OData protocol][odata-filter].

Note

Description Example
Get all users with the name Mary across multiple properties. GET ~/users?$filter=startswith(displayName,'mary') or startswith(givenName,'mary') or startswith(surname,'mary') or startswith(mail,'mary') or startswith(userPrincipalName,'mary')
Get all users with mail domain equal to 'hotmail.com' GET ~/users?$count=true&$filter=endsWith(mail,'@hotmail.com')*
Get all users without assigned licenses GET ~/users?$filter=assignedLicenses/$count eq 0&$count=true*
Get all the signed-in user's events that start after 7/1/2017. GET ~/me/events?$filter=start/dateTime ge '2017-07-01T08:00'.
NOTE: The dateTime property is a String type.
Get all emails from a specific address received by the signed-in user. GET ~/me/messages?$filter=from/emailAddress/address eq 'someuser@example.com'
Get all emails received by the signed-in user in April 2017. GET ~/me/mailFolders/inbox/messages?$filter=ReceivedDateTime ge 2017-04-01 and receivedDateTime lt 2017-05-01
Get all unread mail in the signed-in user's Inbox. GET ~/me/mailFolders/inbox/messages?$filter=isRead eq false
Get all users in the Retail and Sales departments. GET ~/users?$filter=department in ('Retail', 'Sales')
List users with a particular service plan that is in a suspended state. GET ~/users?$filter=assignedPlans/any(a:a/servicePlanId eq 2e2ddb96-6af9-4b1d-a3f0-d6ecfd22edb2 and a/capabilityStatus eq 'Suspended')&$count=true*
List all non-Microsoft 365 groups in an organization. GET ~/groups?$filter=NOT groupTypes/any(c:c eq 'Unified')&$count=true*
List all users whose company name isn't undefined (that is, not a null value) or Microsoft. GET ~/users?$filter=companyName ne null and NOT(companyName eq 'Microsoft')&$count=true*
List all users whose company name is either undefined or Microsoft. GET ~/users?$filter=companyName in (null, 'Microsoft')&$count=true*
Use OData cast to get transitive membership in groups with a display name that starts with 'a' including a count of returned objects. GET ~/me/transitiveMemberOf/microsoft.graph.group?$count=true&$filter=startswith(displayName, 'a')*

Syntax for using the $filter OData query parameter

The following article demonstrates the syntax for using the $filter OData query parameter and its associated operators. The examples are provided for guidance only and don't reflect a comprehensive list for the application of $filter.

These examples show how to use $filter to match against supported properties and relationships that are primitive types, complex types, enumeration types, or a collection of one of these types.

Note

  1. Examples marked with * are only supported with advanced query capabilities.
  2. GUID and DateTimeOffset values aren't enclosed in quotes in $filter expressions.

For single primitive types like String, Int, and dates

Operator Syntax
eq ~/users?$filter=userType eq 'Member'
not ~/users?$filter=not(userType eq 'Member')*
ne ~/users?$filter=companyName ne null*
startsWith ~/users?$filter=startsWith(userPrincipalName, 'admin')
endsWith ~/users?$filter=endsWith(mail,'@outlook.com')*
in ~/users?$filter=userType in ('Guest')
le ~/devices?$filter=registrationDateTime le 2021-01-02T12:00:00Z*
ge ~/devices?$filter=registrationDateTime ge 2021-01-02T12:00:00Z*
not and endsWith ~/users?$filter=not(endsWith(mail, 'OnMicrosoft.com'))*
not and startsWith ~/users?$filter=not(startsWith(mail, 'A'))*
not and eq ~/users?$filter=not(companyName eq 'Contoso E.A.')*
not and in ~/users?$filter=not(userType in ('Member'))*
contains ~/identityGovernance/accessReviews/definitions?$filter=contains(scope/microsoft.graph.accessReviewQueryScope/query, './members')
has ~/identity/conditionalAccess/templates?$filter=scenarios has 'secureFoundation'

For a collection of primitive types

Operator (s) Syntax
eq ~/groups?$filter=groupTypes/any(c:c eq 'Unified')
not ~/groups?$filter=not(groupTypes/any(c:c eq 'Unified'))*
ne ~/users?$filter=companyName ne null*
startsWith ~/users?$filter=businessPhones/any(p:startsWith(p, '44'))*
endsWith ~/users?$filter=endsWith(mail,'@outlook.com')*
not and endsWith ~/groups?$filter=not(endsWith(mail,'OnMicrosoft.com'))*
not and startsWith ~/groups?$filter=not(startsWith(mail,'Pineview'))*
not and eq ~/groups?$filter=not(mail eq 'PineviewSchoolStaff@Contoso.com')*
eq and $count for empty collections ~/users?$filter=assignedLicenses/$count eq 0*
ne and $count for empty collections ~/users?$filter=assignedLicenses/$count ne 0*
not and $count for empty collections ~/users?$filter=not(assignedLicenses/$count eq 0)*
$count for collections with one object ~/servicePrincipals?$filter=owners/$count eq 1*

For GUID types

Operator (s) Syntax
eq ~/servicePrincipals?$filter=appOwnerOrganizationId eq 72f988bf-86f1-41af-91ab-2d7cd011db47*
not ~/servicePrincipals?$filter=not(appOwnerOrganizationId eq 72f988bf-86f1-41af-91ab-2d7cd011db47)&$count=true*

For a collection of GUID types

Operator (s) Syntax
eq ~/devices?$filter=alternativeSecurityIds/any(a:a/type eq 2)*
le ~/devices?$filter=alternativeSecurityIds/any(a:a/type le 2)*
ge ~/devices?$filter=alternativeSecurityIds/any(a:a/type ge 2)*

For a collection of complex types

Operator (s) Syntax
eq ~/users?$filter=authorizationInfo/certificateUserIds/any(x:x eq '9876543210@mil')*
not and eq ~/users?$filter=not(authorizationInfo/certificateUserIds/any(x:x eq '9876543210@mil'))*
startsWith ~/users?$filter=authorizationInfo/certificateUserIds/any(x:startswith(x,'987654321'))*
endsWith ~/users?$filter=proxyAddresses/any(p:endsWith(p,'OnMicrosoft.com'))*

See also