Advanced query capabilities on Microsoft Entra ID objects
Article
Microsoft Graph supports advanced query capabilities on various Microsoft Entra ID objects, also called directory objects, to help you efficiently access data. For example, the addition of not (not), not equals (ne), and ends with (endsWith) operators on the $filter query parameter.
The Microsoft Graph query engine uses an index store to fulfill query requests. To add support for additional query capabilities on some properties, those properties might be indexed in a separate store. This separate indexing improves query performance. However, these advanced query capabilities aren't available by default but, the requestor must set the ConsistencyLevel header to eventualand, except for $search, use the $count query parameter. The ConsistencyLevel header and $count are referred to as advanced query parameters.
For example, to retrieve only inactive user accounts, you can run either of these queries that use the $filter query parameter.
Option 1: Use the $filter query parameter with the eq operator. This request works by default and doesn't require the advanced query parameters.
GET https://graph.microsoft.com/v1.0/users?$filter=accountEnabled eq false
// Code snippets are only available for the latest version. Current version is 5.x
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
var result = await graphClient.Users.GetAsync((requestConfiguration) =>
{
requestConfiguration.QueryParameters.Filter = "accountEnabled eq false";
});
// Code snippets are only available for the latest major version. Current major version is $v1.*
// Dependencies
import (
"context"
msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go"
graphusers "github.com/microsoftgraph/msgraph-sdk-go/users"
//other-imports
)
requestFilter := "accountEnabled eq false"
requestParameters := &graphusers.UsersRequestBuilderGetQueryParameters{
Filter: &requestFilter,
}
configuration := &graphusers.UsersRequestBuilderGetRequestConfiguration{
QueryParameters: requestParameters,
}
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=go
users, err := graphClient.Users().Get(context.Background(), configuration)
// Code snippets are only available for the latest version. Current version is 6.x
GraphServiceClient graphClient = new GraphServiceClient(requestAdapter);
UserCollectionResponse result = graphClient.users().get(requestConfiguration -> {
requestConfiguration.queryParameters.filter = "accountEnabled eq false";
});
# Code snippets are only available for the latest version. Current version is 1.x
from msgraph import GraphServiceClient
from msgraph.generated.users.users_request_builder import UsersRequestBuilder
from kiota_abstractions.base_request_configuration import RequestConfiguration
# To initialize your graph_client, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=python
query_params = UsersRequestBuilder.UsersRequestBuilderGetQueryParameters(
filter = "accountEnabled eq false",
)
request_configuration = RequestConfiguration(
query_parameters = query_params,
)
result = await graph_client.users.get(request_configuration = request_configuration)
Option 2: Use the $filter query parameter with the ne operator. This request isn't supported by default because the ne operator is only supported in advanced queries. Therefore, you must add the ConsistencyLevel header set to eventualand use the $count=true query string.
GET https://graph.microsoft.com/v1.0/users?$filter=accountEnabled ne true&$count=true
ConsistencyLevel: eventual
// Code snippets are only available for the latest version. Current version is 5.x
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
var result = await graphClient.Users.GetAsync((requestConfiguration) =>
{
requestConfiguration.QueryParameters.Filter = "accountEnabled ne true";
requestConfiguration.QueryParameters.Count = true;
requestConfiguration.Headers.Add("ConsistencyLevel", "eventual");
});
// Code snippets are only available for the latest major version. Current major version is $v1.*
// Dependencies
import (
"context"
abstractions "github.com/microsoft/kiota-abstractions-go"
msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go"
graphusers "github.com/microsoftgraph/msgraph-sdk-go/users"
//other-imports
)
headers := abstractions.NewRequestHeaders()
headers.Add("ConsistencyLevel", "eventual")
requestFilter := "accountEnabled ne true"
requestCount := true
requestParameters := &graphusers.UsersRequestBuilderGetQueryParameters{
Filter: &requestFilter,
Count: &requestCount,
}
configuration := &graphusers.UsersRequestBuilderGetRequestConfiguration{
Headers: headers,
QueryParameters: requestParameters,
}
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=go
users, err := graphClient.Users().Get(context.Background(), configuration)
// Code snippets are only available for the latest version. Current version is 6.x
GraphServiceClient graphClient = new GraphServiceClient(requestAdapter);
UserCollectionResponse result = graphClient.users().get(requestConfiguration -> {
requestConfiguration.queryParameters.filter = "accountEnabled ne true";
requestConfiguration.queryParameters.count = true;
requestConfiguration.headers.add("ConsistencyLevel", "eventual");
});
# Code snippets are only available for the latest version. Current version is 1.x
from msgraph import GraphServiceClient
from msgraph.generated.users.users_request_builder import UsersRequestBuilder
from kiota_abstractions.base_request_configuration import RequestConfiguration
# To initialize your graph_client, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=python
query_params = UsersRequestBuilder.UsersRequestBuilderGetQueryParameters(
filter = "accountEnabled ne true",
count = True,
)
request_configuration = RequestConfiguration(
query_parameters = query_params,
)
request_configuration.headers.add("ConsistencyLevel", "eventual")
result = await graph_client.users.get(request_configuration = request_configuration)
Using $filter and $orderby together is supported only with advanced queries.
$expand is not currently supported with advanced queries.
The advanced query capabilities are currently not available for Azure AD B2C tenants.
To use advanced query capabilities in batch requests, specify the ConsistencyLevel header in the JSON body of the POST request.
Support for filter by properties of Microsoft Entra ID (directory) objects
Properties of directory objects behave differently in their support for query parameters. The following are common scenarios for directory objects:
Queries that are supported by default will also work with advanced query parameters, but the response will be eventually consistent.
The in operator is supported by default whenever eq operator is supported by default.
The endswith operator is supported only with advanced query parameters by mail, otherMails, userPrincipalName, and proxyAddresses properties.
Getting empty collections (/$count eq 0, /$count ne 0) and collections with less than one object (/$count eq 1, /$count ne 1) is supported only with advanced query parameters.
The not and ne negation operators are supported only with advanced query parameters.
All properties that support the eq operator also supports the ne or not operators.
The following tables summarize support for $filter operators by properties of directory objects, and indicates where querying is supported through advanced query capabilities.
Legend
The $filter operator works by default for that property.
The $filter operator requiresadvanced query parameters, which are:
ConsistencyLevel=eventual header
$count=true query string
The $filter operator isn't supported on that property. Send us feedback to request that this property support $filter for your scenarios.
Blank cells indicate that the query isn't valid for that property.
The null value column indicates that the property is nullable and filterable using null.
Properties that aren't listed here don't support $filter at all.
Administrative unit properties
Property
eq
startsWith
eq Null
description
displayName
isMemberManagementRestricted
membershipRule
membershipRuleProcessingState
scopedRoleMembers/any(s:s/id)
Application properties
Property
eq
startsWith
ge/le
eq Null
appId
createdDateTime
createdOnBehalfOf/id
description
disabledByMicrosoftStatus
displayName
federatedIdentityCredentials/any(f:f/issuer)
federatedIdentityCredentials/any(f:f/name)
federatedIdentityCredentials/any(f:f/subject)
identifierUris/any(p:p)
info/logoUrl
info/termsOfServiceUrl
notes
publicClient/redirectUris/any(p:p)
publisherDomain
requiredResourceAccess/any(r:r/resourceAppId)
serviceManagementReference
signInAudience
spa/redirectUris/any(p:p)
tags/any(p:p)
uniqueName
verifiedPublisher/displayName
web/homePageUrl
web/redirectUris/any(p:p)
The following properties of the application entity support $count of a collection in a filter expression.
Property
eq Count 0
eq Count 1
extensionProperties/$count
federatedIdentityCredentials/$count
Contract properties
Property
eq
startsWith
customerId
defaultDomainName
displayName
Device properties
Property
eq
startsWith
ge/le
eq Null
accountEnabled
alternativeSecurityIds/any(a:a/identityProvider)
alternativeSecurityIds/any(a:a/type)
approximateLastSignInDateTime
deviceCategory
deviceId
deviceOwnership
displayName
enrollmentProfileName
extensionAttributes/extensionAttribute1-15
hostnames/any(p:p)
isCompliant
isManaged
isRooted
managementType
manufacturer
mdmAppId
model
onPremisesLastSyncDateTime
onPremisesSecurityIdentifier
onPremisesSyncEnabled
operatingSystem
operatingSystemVersion
physicalIds/any(p:p)
profileType
registrationDateTime
trustType
The following properties of the device entity support $count of a collection in a filter expression.
Support for sorting by properties of Microsoft Entra ID (directory) objects
The following table summarizes support for $orderby by properties of directory objects and indicates where sorting is supported through advanced query capabilities.
Legend
The $orderby operator works by default for that property.
The $orderby operator requiresadvanced query parameters, which are:
Error handling for advanced queries on directory objects
The following section provides examples of common error scenarios when you don't use advanced query parameters where required.
Counting directory objects is only supported using the advanced queries parameters. If the ConsistencyLevel=eventual header isn't specified, the request returns an error when the $count URL segment (/$count) is used or silently ignores the $count query parameter (?$count=true) if it's used.
// Code snippets are only available for the latest version. Current version is 5.x
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
await graphClient.Users.Count.GetAsync();
// Code snippets are only available for the latest major version. Current major version is $v1.*
// Dependencies
import (
"context"
msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go"
//other-imports
)
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=go
graphClient.Users().Count().Get(context.Background(), nil)
// Code snippets are only available for the latest version. Current version is 6.x
GraphServiceClient graphClient = new GraphServiceClient(requestAdapter);
graphClient.users().count().get();
<?php
use Microsoft\Graph\GraphServiceClient;
$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
$graphServiceClient->users()->count()->get()->wait();
# Code snippets are only available for the latest version. Current version is 1.x
from msgraph import GraphServiceClient
# To initialize your graph_client, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=python
await graph_client.users.count.get()
GET https://graph.microsoft.com/v1.0/applications?$search="displayName:Browser"
// Code snippets are only available for the latest version. Current version is 5.x
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
var result = await graphClient.Applications.GetAsync((requestConfiguration) =>
{
requestConfiguration.QueryParameters.Search = "\"displayName:Browser\"";
});
// Code snippets are only available for the latest major version. Current major version is $v1.*
// Dependencies
import (
"context"
msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go"
graphapplications "github.com/microsoftgraph/msgraph-sdk-go/applications"
//other-imports
)
requestSearch := "\"displayName:Browser\""
requestParameters := &graphapplications.ApplicationsRequestBuilderGetQueryParameters{
Search: &requestSearch,
}
configuration := &graphapplications.ApplicationsRequestBuilderGetRequestConfiguration{
QueryParameters: requestParameters,
}
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=go
applications, err := graphClient.Applications().Get(context.Background(), configuration)
// Code snippets are only available for the latest version. Current version is 6.x
GraphServiceClient graphClient = new GraphServiceClient(requestAdapter);
ApplicationCollectionResponse result = graphClient.applications().get(requestConfiguration -> {
requestConfiguration.queryParameters.search = "\"displayName:Browser\"";
});
# Code snippets are only available for the latest version. Current version is 1.x
from msgraph import GraphServiceClient
from msgraph.generated.applications.applications_request_builder import ApplicationsRequestBuilder
from kiota_abstractions.base_request_configuration import RequestConfiguration
# To initialize your graph_client, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=python
query_params = ApplicationsRequestBuilder.ApplicationsRequestBuilderGetQueryParameters(
search = "\"displayName:Browser\"",
)
request_configuration = RequestConfiguration(
query_parameters = query_params,
)
result = await graph_client.applications.get(request_configuration = request_configuration)
{
"error": {
"code": "Request_UnsupportedQuery",
"message": "Request with $search query parameter only works through MSGraph with a special request header: 'ConsistencyLevel: eventual'",
"innerError": {
"date": "2021-05-27T14:26:47",
"request-id": "9b600954-ba11-4899-8ce9-6abad341f299",
"client-request-id": "7964ef27-13a3-6ca4-ed7b-73c271110867"
}
}
}
If a property or query parameter in the URL is supported only in advanced queries but either the ConsistencyLevel header or the $count=true query string is missing, the request returns an error.
GET https://graph.microsoft.com/beta/users?$filter=endsWith(userPrincipalName,'%23EXT%23@contoso.com')
// Code snippets are only available for the latest version. Current version is 5.x
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
var result = await graphClient.Users.GetAsync((requestConfiguration) =>
{
requestConfiguration.QueryParameters.Filter = "endsWith(userPrincipalName,'";
});
// Code snippets are only available for the latest major version. Current major version is $v0.*
// Dependencies
import (
"context"
msgraphsdk "github.com/microsoftgraph/msgraph-beta-sdk-go"
graphusers "github.com/microsoftgraph/msgraph-beta-sdk-go/users"
//other-imports
)
requestFilter := "endsWith(userPrincipalName,'"
requestParameters := &graphusers.UsersRequestBuilderGetQueryParameters{
Filter: &requestFilter,
}
configuration := &graphusers.UsersRequestBuilderGetRequestConfiguration{
QueryParameters: requestParameters,
}
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=go
users, err := graphClient.Users().Get(context.Background(), configuration)
// Code snippets are only available for the latest version. Current version is 6.x
GraphServiceClient graphClient = new GraphServiceClient(requestAdapter);
UserCollectionResponse result = graphClient.users().get(requestConfiguration -> {
requestConfiguration.queryParameters.filter = "endsWith(userPrincipalName,'";
});
# Code snippets are only available for the latest version. Current version is 1.x
from msgraph_beta import GraphServiceClient
from msgraph_beta.generated.users.users_request_builder import UsersRequestBuilder
from kiota_abstractions.base_request_configuration import RequestConfiguration
# To initialize your graph_client, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=python
query_params = UsersRequestBuilder.UsersRequestBuilderGetQueryParameters(
filter = "endsWith(userPrincipalName,'",
)
request_configuration = RequestConfiguration(
query_parameters = query_params,
)
result = await graph_client.users.get(request_configuration = request_configuration)
{
"error": {
"code": "Request_UnsupportedQuery",
"message": "Operator 'endsWith' is not supported because the required parameters might be missing. Try adding $count=true query parameter and ConsistencyLevel:eventual header. Refer to https://aka.ms/graph-docs/advanced-queries for more information",
"innerError": {
"date": "2023-07-14T08:43:39",
"request-id": "b3731da7-5c46-4c37-a8e5-b190124d2531",
"client-request-id": "a1556ddf-4794-929d-0105-b753a78b4c68"
}
}
}
If a property isn't indexed to support a query parameter, the request returns an error even if advanced query parameters are specified. For example, the createdDateTime property of the group resource isn't indexed for query capabilities.
GET https://graph.microsoft.com/beta/groups?$filter=createdDateTime ge 2021-11-01&$count=true
ConsistencyLevel: eventual
// Code snippets are only available for the latest version. Current version is 5.x
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
var result = await graphClient.Groups.GetAsync((requestConfiguration) =>
{
requestConfiguration.QueryParameters.Filter = "createdDateTime ge 2021-11-01";
requestConfiguration.QueryParameters.Count = true;
requestConfiguration.Headers.Add("ConsistencyLevel", "eventual");
});
// Code snippets are only available for the latest major version. Current major version is $v0.*
// Dependencies
import (
"context"
abstractions "github.com/microsoft/kiota-abstractions-go"
msgraphsdk "github.com/microsoftgraph/msgraph-beta-sdk-go"
graphgroups "github.com/microsoftgraph/msgraph-beta-sdk-go/groups"
//other-imports
)
headers := abstractions.NewRequestHeaders()
headers.Add("ConsistencyLevel", "eventual")
requestFilter := "createdDateTime ge 2021-11-01"
requestCount := true
requestParameters := &graphgroups.GroupsRequestBuilderGetQueryParameters{
Filter: &requestFilter,
Count: &requestCount,
}
configuration := &graphgroups.GroupsRequestBuilderGetRequestConfiguration{
Headers: headers,
QueryParameters: requestParameters,
}
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=go
groups, err := graphClient.Groups().Get(context.Background(), configuration)
// Code snippets are only available for the latest version. Current version is 6.x
GraphServiceClient graphClient = new GraphServiceClient(requestAdapter);
GroupCollectionResponse result = graphClient.groups().get(requestConfiguration -> {
requestConfiguration.queryParameters.filter = "createdDateTime ge 2021-11-01";
requestConfiguration.queryParameters.count = true;
requestConfiguration.headers.add("ConsistencyLevel", "eventual");
});
# Code snippets are only available for the latest version. Current version is 1.x
from msgraph_beta import GraphServiceClient
from msgraph_beta.generated.groups.groups_request_builder import GroupsRequestBuilder
from kiota_abstractions.base_request_configuration import RequestConfiguration
# To initialize your graph_client, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=python
query_params = GroupsRequestBuilder.GroupsRequestBuilderGetQueryParameters(
filter = "createdDateTime ge 2021-11-01",
count = True,
)
request_configuration = RequestConfiguration(
query_parameters = query_params,
)
request_configuration.headers.add("ConsistencyLevel", "eventual")
result = await graph_client.groups.get(request_configuration = request_configuration)
{
"error": {
"code": "Request_UnsupportedQuery",
"message": "Unsupported or invalid query filter clause specified for property 'createdDateTime' of resource 'Group'.",
"innerError": {
"date": "2023-07-14T08:42:44",
"request-id": "b6a5f998-94c8-430d-846d-2eaae3031492",
"client-request-id": "2be83e05-649e-2508-bcd9-62e666168fc8"
}
}
}
However, a request that includes query parameters might fail silently. For example, for unsupported query parameters and for unsupported combinations of query parameters. In these cases, examine the data returned by the request to determine whether the query parameters you specified had the desired effect. For example, in the following example, the @odata.count parameter is missing even if the query is successful.
GET https://graph.microsoft.com/v1.0/users?$count=true
// Code snippets are only available for the latest version. Current version is 5.x
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
var result = await graphClient.Users.GetAsync((requestConfiguration) =>
{
requestConfiguration.QueryParameters.Count = true;
});
// Code snippets are only available for the latest major version. Current major version is $v1.*
// Dependencies
import (
"context"
msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go"
graphusers "github.com/microsoftgraph/msgraph-sdk-go/users"
//other-imports
)
requestCount := true
requestParameters := &graphusers.UsersRequestBuilderGetQueryParameters{
Count: &requestCount,
}
configuration := &graphusers.UsersRequestBuilderGetRequestConfiguration{
QueryParameters: requestParameters,
}
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=go
users, err := graphClient.Users().Get(context.Background(), configuration)
// Code snippets are only available for the latest version. Current version is 6.x
GraphServiceClient graphClient = new GraphServiceClient(requestAdapter);
UserCollectionResponse result = graphClient.users().get(requestConfiguration -> {
requestConfiguration.queryParameters.count = true;
});
# Code snippets are only available for the latest version. Current version is 1.x
from msgraph import GraphServiceClient
from msgraph.generated.users.users_request_builder import UsersRequestBuilder
from kiota_abstractions.base_request_configuration import RequestConfiguration
# To initialize your graph_client, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=python
query_params = UsersRequestBuilder.UsersRequestBuilderGetQueryParameters(
count = True,
)
request_configuration = RequestConfiguration(
query_parameters = query_params,
)
result = await graph_client.users.get(request_configuration = request_configuration)