Rate this page

Searching for resources

A SCIM search request involves three elements:

  1. The base search path. This designates a resource type that constrains the scope of the search (e.g., /scim/v2/Users). It may not be a specific SCIM resource (e.g., /scim/v2/Users/{userId}).
  2. A filter. The search filter constrains the results of the query to those resources matching an attribute value asserted by the filter.
  3. Optional pagination controls. Pagination parameters can be used to split a large number of search results into multiple result sets.

Let’s get right to an example before going over the details.

Filter filter = Filter.and(
    Filter.ew("emails.value", "example.com"), // ew == "ends with"
    Filter.eq("name.familyName", "Lem") // eq == "equals"
);

ListResponse<GenericScimResource> result =
    scimService.searchRequest("Users")
        .filter(filter.toString())
        .page(1, 1) // (Pagination start index, results per page)
        .attributes("name", "emails")
        .invoke(GenericScimResource.class);

System.out.println("Total results: " + result.getTotalResults());
for (GenericScimResource matchingResource : result.getResources()) {
  System.out.println(matchingResource.getStringValue("name.givenName"));
}

What does this example do?

  • It builds a search filter: emails.value ew "example.com" and name.familyName eq "Lem"
  • It searches for any matches under the “Users” resource type. If there are any matches, one result will be returned with the attributes name and emails The return type will be GenericScimResource.
  • Prints out information from the search result.

Filters

A search filter typically takes the form <attribute> <operator> <value>. For example:

filter=userName eq "pkd"

filter=attribute operator value

Operators are listed in the SCIM API reference.

As with everything else in SCIM, attributes must be prefixed with a schema URN if they do not belong to the resource type’s core schema.

Another form of search filter is a complex filter. This takes the form <complex attribute>[<simple filter>]. For example:

filter=name[givenName eq "Philip"]

This example means: Find resources where the name attribute has the sub-attribute givenName with a value of “Philip”.

The Filter class

When using the SCIM 2 SDK, filters can either be specified as strings or built using the Filter class. The Filter class provides various static methods corresponding to filter operators; you build search filters by nesting method calls. A few examples should make this clear.

The following performs an equality search for the userName attribute and a specific value:

Filter.eq("userName", "slem")

The following performs a ‘starts with’ search for the name.givenName attribute and a specific string:

Filter.sw("name.givenName", "Stan")

And the following uses the and operator to combine the above two searches:

Filter.and(
  Filter.eq("userName", "slem"),
  Filter.sw("name.givenName", "Stan")
)

Complex filters are specified using the hasComplexValue(...) method. The following expression is equivalent to the filter emails[name eq "slem@example.com"]:

Filter.hasComplexValue(
  "emails",
  Filter.eq("value", "slem@example.com")
)

Caveats

If you’re accustomed to RDBMS query languages like SQL, SCIM filters may take you by surprise. A SCIM search expression acts strictly as a filter, not as a selector. Given a base resource type, it filters out any non-matching resources — it does not offer the ability to join data across related but distinct resources, for example.

Another difference is that SCIM search results are returned by resource, not by value. Let’s explain this with an example. Say that you search using the filter emails[type eq "work" and value ew "work.com"]. This means give me any resources with an emails attribute of type “work” and a value that ends with “work.com”. The search result will include any resources that match this filter, and each resource will include all email address values, not just those with type “work”.

The lookthrough limit

Certain searches may return the error “The search request matched too many results”, indicating that the search produced more results than the Data Governance Server can process. For example:

  • Attempting to retrieve all resources of a given type: GET /scim/v2/Users
  • Attempting to page through all resources of a given type: GET /scim/v2/Users?startIndex=1&count=5
  • Searching with a filter that returns a large result set: GET /scim/v2/Users?filter=userName+sw+"user"

This happens because the DG’s policy engine must process the full search result set received from the store adapter so that it can filter the response to be passed to the client; to avoid exhausting available memory, the DG must set an upper bound on the size of the full search result set. This upper bound is set on a per-resource type basis using the lookthrough-limit configuration property. For more information on the lookthrough limit and how to change it, consult the Ping Identity Data Governance Broker Configuration Reference.

To avoid exceeding the lookthrough limit, construct your searches with as specific a filter as possible, and bear in mind that providing pagination parameters alone is not sufficient.

Pagination

A client may request that the server segment search results into pages. Pagination is handled using the following search parameters:

Parameter Description
startIndex The 1-based index of the first query result.
count A non-negative integer specifying the maximum number of matching resources to return per page.

A client can get the total number of matches for a particular filter without actually downloading a result set by specifying a count of 0.

ListResponse<GenericScimResource> result =
    scimService.searchRequest("Users")
        .filter(filter.toString())
        .page(1, 0) // (Pagination start index, results per page)
        .attributes("name", "emails")
        .invoke(GenericScimResource.class);

System.out.println("Total results: " + result.getTotalResults());
// result.getResources() will be empty.