PingIDM 8.0.0

Configuring relationships

Relationships are references between managed objects. They are defined in your managed object configuration file. You can interact with relationships over REST using the relationship’s endpoint, openidm/managed/user/userName/relationshipName?_queryFilter=true.

Learn more about relationships in:

Learn more about interacting with relationships over REST in:

When modeling relationships, be aware of bidirectional relationships and model them properly in your schema.

Roles and Organizations are implemented using relationships, but you can create relationships between any managed object type.

You can also:

IDM maintains referential integrity by deleting the relationship reference if the object referred to by that relationship is deleted.

Example relationship: manager

The default configuration includes a relationship named manager that lets you configure a relationship between two managed users. This relationship is a good example for understanding how relationships work.

The default manager relationship is configured as follows:

"manager" : {
    "type" : "relationship",
    "validate" : true,
    "reverseRelationship" : true,
    "reversePropertyName" : "reports",
    "description" : "Manager",
    "title" : "Manager",
    "viewable" : true,
    "searchable" : false,
    "usageDescription" : "",
    "isPersonal" : false,
    "properties" : {
        "_ref" : {
            "description" : "References a relationship from a managed object",
            "type" : "string"
        },
        "_refProperties" : {
            "description" : "Supports metadata within the relationship",
            "type" : "object",
            "title" : "Manager _refProperties",
            "properties" : {
                "_id" : {
                    "description" : "_refProperties object ID",
                    "type" : "string"
                }
            }
        }
    },
    "resourceCollection" : [
        {
            "path" : "managed/user",
            "label" : "User",
            "query" : {
                "queryFilter" : "true",
                "fields" : [
                    "userName",
                    "givenName",
                    "sn"
                ]
            }
        }
    ],
    "userEditable" : false
},

Retrieve relationship data

There are two ways to retrieve data about a relationship over REST, querying the relationship endpoint or reading relationship fields.

Querying the relationship endpoint supports filtering and paginating the results. It’s the safest and most efficient way of retrieving data.

Reading relationship fields does not support filtering or paginating results. To prevent problems that could result from requesting a large amount of data, use this method only in situations where you are certain there are few results.

Query a relationship endpoint

You can retrieve a managed object’s relationship data by querying the relationship endpoint. The endpoint’s name is the name of the relationship field.

A relationship endpoint query can use the _queryFilter and _pageSize parameters to filter and paginate large numbers of results. To avoid the risk of a large query overwhelming your system, use this method whenever possible.

The _queryFilter parameter can filter by any fields which are indexed attributes of the related object.

The following example demonstrates querying managed user bjensen for all reports:

curl \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"http://localhost:8080/openidm/managed/user/bjensen/reports?_queryFilter=true"
{
  "result": [
    {
      "_id": "78483e83-9577-40cd-a1d4-6ea0a896e916-4311",
      "_rev": "78483e83-9577-40cd-a1d4-6ea0a896e916-4312",
      "_ref": "managed/user/psmith",
      "_refResourceCollection": "managed/user",
      "_refResourceId": "psmith",
      "_refProperties": {
        "_id": "78483e83-9577-40cd-a1d4-6ea0a896e916-4311",
        "_rev": "78483e83-9577-40cd-a1d4-6ea0a896e916-4312"
      }
    },
    {
      "_id": "78483e83-9577-40cd-a1d4-6ea0a896e916-4934",
      "_rev": "78483e83-9577-40cd-a1d4-6ea0a896e916-4935",
      "_ref": "managed/user/scarter",
      "_refResourceCollection": "managed/user",
      "_refResourceId": "scarter",
      "_refProperties": {
        "_id": "78483e83-9577-40cd-a1d4-6ea0a896e916-4934",
        "_rev": "78483e83-9577-40cd-a1d4-6ea0a896e916-4935"
      }
    }
  ],
  "resultCount": 2,
  "pagedResultsCookie": null,
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": -1
}

The following example demonstrates querying managed user bjensen for all reports where the sn is Smith:

curl \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"http://localhost:8080/openidm/managed/user/bjensen/reports?_queryFilter=sn+eq+'Smith'&_pageSize=1"
{
  "result": [
    {
      "_id": "78483e83-9577-40cd-a1d4-6ea0a896e916-4311",
      "_rev": "78483e83-9577-40cd-a1d4-6ea0a896e916-4312",
      "_ref": "managed/user/psmith",
      "_refResourceCollection": "managed/user",
      "_refResourceId": "psmith",
      "_refProperties": {
        "_id": "78483e83-9577-40cd-a1d4-6ea0a896e916-4311",
        "_rev": "78483e83-9577-40cd-a1d4-6ea0a896e916-4312"
      }
    }
  ],
  "resultCount": 1,
  "pagedResultsCookie": null,
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": -1
}

You can also pass the _fields query parameter to include them in the response, demonstrated here with userName and phoneNumber:

curl \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \ \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"http://localhost:8080/openidm/managed/user/bjensen/reports?_queryFilter=sn+eq+'Smith'&_fields=userName,phoneNumber&_pageSize=1"
{
  "result" : [ {
    "_id" : "78483e83-9577-40cd-a1d4-6ea0a896e916-45700",
    "_rev" : "78483e83-9577-40cd-a1d4-6ea0a896e916-45701",
    "_ref" : "managed/user/psmith",
    "_refResourceCollection" : "managed/user",
    "_refResourceId" : "psmith",
    "_refResourceRev" : "d776f795-512f-4c09-a673-1f081a8ef3ef-4955",
    "_refProperties" : {
      "_id" : "78483e83-9577-40cd-a1d4-6ea0a896e916-45700",
      "_rev" : "78483e83-9577-40cd-a1d4-6ea0a896e916-45701"
    },
    "userName" : "psmith",
    "phoneNumber" : "0831245986"
  } ],
  "resultCount" : 1,
  "pagedResultsCookie" : null,
  "totalPagedResultsPolicy" : "NONE",
  "totalPagedResults" : -1,
  "remainingPagedResults" : -1
}

When you query an endpoint which is a collection, you must use the _queryFilter parameter, or you’ll receive an error with an HTTP 400 error code. If you don’t want to filter the results, pass _queryFilter=true.

Learn more about _queryFilter in Query and Constructing queries.

Read relationship fields

To read relationship fields, query a managed object and pass the _fields parameter to request associated data fields.

Do not use _fields to request a field that is a relationship with more than a few members, as this data cannot be filtered or paginated.

The following example reads a singleton relationship (manager) associated with a managed user (psmith):

curl \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"http://localhost:8080/openidm/managed/user/psmith?_fields=manager"
{
  "_id": "0cb7c704-77ab-4211-9f13-04e45847f5e9-17222",
  "_rev": "0cb7c704-77ab-4211-9f13-04e45847f5e9-17223",
  "_ref": "managed/user/bjensen",
  "_refResourceCollection": "managed/user",
  "_refResourceId": "bjensen",
  "_refProperties": {
    "_id": "0cb7c704-77ab-4211-9f13-04e45847f5e9-17222",
    "_rev": "0cb7c704-77ab-4211-9f13-04e45847f5e9-17223"
  }
}

When you’re reading relationship fields, you can use the managed object endpoint directly using the following syntax:

  • relatedObject/property (for a simple string value)

  • relatedObject/*/property (for an array of values)

This example demonstrates retrieving the mail and phoneNumber properties from psmith’s manager using this method:

curl \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"http://localhost:8080/openidm/managed/user/psmith?_fields=manager/mail,manager/phoneNumber"
{
  "_id": "psmith",
  "_rev": "0000000014c0b68d",
  "manager": {
    "_rev": "000000005bac8c10",
    "_id": "bjensen",
    "phoneNumber": "12345678",
    "mail": "bjensen@example.com",
    "_ref": "managed/user/bjensen",
    "_refResourceCollection": "managed/user",
    "_refResourceId": "bjensen",
    "_refProperties": {
      "_id": "42418f09-ad6c-4b77-bf80-2a12d0c44678",
      "_rev": "00000000288b921e"
    }
  }
}

Create a relationship

To create a relationship between two managed objects, send a POST request to the relationship’s endpoint with a _ref parameter containing the path to the other side of the relationship.

For example, suppose the user psmith has the user bjensen as a manager. The following call creates the manager relationship between them:

curl \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--request POST \
--data '{
  "_ref" : "managed/user/bjensen"
}' \
"http://localhost:8080/openidm/managed/user/psmith/manager"
{
  "_id": "0cb7c704-77ab-4211-9f13-04e45847f5e9-82148",
  "_rev": "0cb7c704-77ab-4211-9f13-04e45847f5e9-82149",
  "_ref": "managed/user/bjensen",
  "_refResourceCollection": "managed/user",
  "_refResourceId": "bjensen",
  "_refProperties": {
    "_id": "0cb7c704-77ab-4211-9f13-04e45847f5e9-82148",
    "_rev": "0cb7c704-77ab-4211-9f13-04e45847f5e9-82149"
  }
}

To learn more about the _ref parameter or the relationship reference properties in general, refer to Relationship properties.

Creating a relationship as part of a created object

In addition to creating a relationship between two existing managed objects, you can create a relationship at the same time as you create a managed object. For example, imagine that you are creating a new user, psmith, and that psmith’s manager will be bjensen. You would create psmith’s user entry, and reference bjensen’s entry with the _ref property, as follows:

curl \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Accept-API-Version: resource=1.0" \
--header "If-None-Match: *" \
--header "Content-Type: application/json" \
--request PUT \
"http://localhost:8080/openidm/managed/user/psmith" \
--data '{
    "_id": "psmith",
    "_rev": "00000000ec41097c",
    "sn": "Smith",
    "userName": "psmith",
    "givenName": "Patricia",
    "displayName": "Patti Smith",
    "description": "psmith - new user",
    "mail": "psmith@example.com",
    "phoneNumber": "0831245986",
    "manager": {
      "_ref": "managed/user/bjensen"
    }
  }'
Relationship information is not returned by default. To show the relationship in psmith’s entry, you must explicitly request her manager entry, as follows:
curl \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"http://localhost:8080/openidm/managed/user/psmith?_fields=manager"
{
  "_id": "psmith",
  "_rev": "00000000ec41097c",
  "manager": {
    "_ref": "managed/user/bjensen",
    "_refResourceCollection": "managed/user",
    "_refResourceId": "bjensen",
    "_refProperties": {
      "_id": "ffc6f0f3-93db-4939-b9eb-1f8389a59a52",
      "_rev": "0000000081aa991a"
    }
  }
}

To learn more about the _ref parameter or the relationship reference properties in general, refer to Relationship properties.

Update a relationship

You can update a managed object’s relationship data by making a PUT request to its endpoint. The endpoint’s name is the name of the relationship field.

When you update a relationship, the related objects automatically update to reflect the new state. In the following example, scarter’s reports entry is automatically updated when the change to psmith’s manager entry is updated.

The following example updates psmith’s manager to scarter:

curl \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \ \
--header "Accept-API-Version: resource=1.0" \
--header "If-Match: *" \
--header "Content-Type: application/json" \
--request PUT \
--data '{
  "_ref":"managed/user/scarter"
}' \
"http://localhost:8080/openidm/managed/user/psmith/manager"
{
  "_id": "0cb7c704-77ab-4211-9f13-04e45847f5e9-82148",
  "_rev": "0cb7c704-77ab-4211-9f13-04e45847f5e9-108753",
  "_ref": "managed/user/scarter",
  "_refResourceCollection": "managed/user",
  "_refResourceId": "scarter",
  "_refProperties": {
    "_id": "0cb7c704-77ab-4211-9f13-04e45847f5e9-82148",
    "_rev": "0cb7c704-77ab-4211-9f13-04e45847f5e9-108753"
  }
}

Delete a relationship

You can delete a relationship by sending a DELETE request to its endpoint.

The following example deletes psmith’s manager:

curl \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \\
--header "Accept-API-Version: resource=1.0" \
--request DELETE \
"http://localhost:8080/openidm/managed/user/psmith/manager"

Relationship properties

Relationships have the following specific configurable properties:

Most of these properties apply to any managed object type.
type (string)

The object type. Must be relationship for a relationship object.

returnByDefault (boolean true, false)

Specifies whether the relationship should be returned as part of the response. The returnByDefault property is not specific to relationships. This flag applies to all managed object types. However, relationship properties are not returned by default, unless explicitly requested.

reverseRelationship (boolean true, false)

Specifies whether this is a bidirectional relationship.

reversePropertyName (string)

The corresponding property name, in the case of a bidirectional relationship. For example, the manager property has a reversePropertyName of reports.

resourceCollection (JSON object)

The collection of resources (objects) on which this relationship is based (for example, managed/user objects).

Relationship reference properties

When you have defined a relationship, you can use the relationship properties to reference one managed user from another. These properties make up a relationship reference:

_ref (JSON object)

Specifies how the relationship between two managed objects is referenced.

The value of the _ref property is a derived path that is a combination of _refResourceCollection and a URL-encoded _refResourceId.

_refResourceCollection

Specifies the container of the referenced object (for example, managed/user).

_refResourceId

Specifies the ID of the referenced object. This is generally a system-generated UUID, such as 9dce06d4-2fc1-4830-a92b-bd35c2f6bcbb. For clarity, this documentation uses client-assigned IDs such as bjensen and psmith.

_refProperties (JSON object)

Any required properties from the relationship that should be included in the managed object. The _refProperties field includes a unique ID (_id) and the revision (_rev) of the object. _refProperties can also contain arbitrary fields to support metadata within the relationship.