Search query aggregations are specialized searches that can only be done via the POST v3/search/aggregate API endpoint. In this article we will explain how to use this API endpoint with a couple examples and use cases.
Let's say our organization operates in multiple regions around the world with employees in each region. We can store the region information in a custom identity attribute, so we know which region each identity belongs to. In the IdentityNow search user interface, we can search for identities in a particular region with a search query like this:
attributes.region:Europe
We would then see the identities in the Europe region returned in the search results:
But what if we wanted to find out how many identities were in each region? We are not able to do that kind of aggregate function search in the UI. We would need to download the results in a csv file and sort and filter in a spreadsheet application.
Instead, we can do a search like this via the POST v3/search/aggregate API endpoint. There are several types of search query aggregations that can be performed with this API endpoint. For this use case, we will use the bucket search aggregation. We need to construct a JSON request body specifying the attributes.region attribute as the field on which we will base the aggregate search, i.e., the type of "bucket" by which we will categorize the identities:
{
"aggregationType": "SAILPOINT",
"aggregations": {
"bucket": {
"field": "attributes.region"
}
}
}
We see the JSON response body returned in Postman includes a buckets array. Each item in this array represents one of our region attribute values and how many identities are in that region. The key attribute is the region attribute value, and the doc_count attribute is how many identities have that value in the attributes.region attribute. We have 21 identities in the Europe region, 15 in the Americas region, and 8 in the Asia-Pacific region:
We also see that the JSON response body includes the hits array which contains objects in the tenant. This may return more data than is wanted or needed. You can add the indices array to the JSON request body to limit which objects are returned. In this case, we would specify the identities enum value in the indices array, and only identity objects would be returned:
{
"aggregationType": "SAILPOINT",
"aggregations": {
"bucket": {
"field": "attributes.region"
}
},
"indices": [
"identities"
]
}
Alternatively, you can set the limit query param to "0", and the hits array will not be included in the JSON response body:
We can do a more specialized bucket search query aggregation by adding additional configuration to the JSON request body. We are able to add top level search query criteria to limit the data where the search query aggregation is applied, limit the fields that are returned with the queryResultFilter nested attribute, and even sort the results returned in the hits array.
For example, we could do a search aggregation query to determine how many identities in the Information Technology department are in each of our global locations, if any. We can then choose only specific fields of the identity object to be returned, and we can sort the returned identity objects by location.
Our "bucket" field attribute value is now the attributes.location identity attribute. We have added the query nested object, and our query attribute value is "attributes.department:\"Information Technology\"" so that the search query aggregation will only be applied to identities in the Information Technology department. (Note the backslash character that escapes the double quote character in our query. Double quotes are required so that "Information Technology" is evaluated as one string value instead of an implicit OR search between "Information" and "Technology".) Within the queryResultFilter nested attribute, we have added our desired return fields in the includes array, so the entire identity objects won't be returned. Lastly, we have added the sort attribute which will sort the identities returned in the hits array by their attributes.location value:
{
"aggregationType": "SAILPOINT",
"aggregations": {
"bucket": {
"field": "attributes.location"
}
},
"indices": [
"identities"
],
"query": {
"query": "attributes.department:\"Information Technology\""
},
"queryResultFilter": {
"includes": [
"name",
"email",
"attributes.location",
"attributes.title"
]
},
"sort": [
"+attributes.location"
]
}
The JSON response body returned in Postman shows us that there are 5 identities in the Information Technology department located in Brussels and 2 located in Singapore. The returned identity objects in the hits array only include the fields we specified in the queryResultFilter nested object includes array, and they are sorted by location so we see the identities in Brussels first: