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 applied against 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

Microsoft Graph supports the use of following operators and functions. However, support by individual resources and its properties or relationships may vary. In addition, some properties and relationships support $filter only with advanced queries. See the specific resource documentation for details, and Syntax for using the filter OData query parameter for examples of how to use these operators and functions.

Operator type Operator
Equality operators
  • Equals (eq)
  • Not equals (ne)
  • Logical negation (not)
  • In (in)
  • Has (has)


Note: When using the in operator, the request is limited to 15 expressions in the filter clause by default or a URL length of 2,048 characters when using advanced query capabilities.
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)

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 resources.

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 query string shows the syntax for 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.

The equivalent syntax in C# and LINQ is as follows:

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 at least one 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 at least one 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. Currently, it isn't supported in Microsoft Graph.

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.

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 of the event entity 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.

Note

  • GUID and DateTimeOffset values aren't enclosed in quotes in $filter expressions.

** : This example is only supported with advanced query capabilities.

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=mail in ('mail1@domain.com', 'mail2@domain.com')

Note: For query strings using in operator, the request is limited to 15 expressions in the filter clause by default or a URL length of 2,048 characters when using advanced query capabilities.
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, 'contoso.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,'contoso.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) **

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=certificateUserIds/any(x:x eq '9876543210@mil') **
not and eq ~/users?$filter=not(certificateUserIds/any(x:x eq '9876543210@mil')) **
startswith ~/users?$filter=certificateUserIds/any(x:startswith(x,'987654321')) **
endswith ~/users?$filter=proxyAddresses/any(p:endswith(p,'contoso.com')) **