Uploaded image for project: 'OpenIDM'
  1. OpenIDM
  2. OPENIDM-3318

Support for join operations between managed entities

    XMLWordPrintable

    Details

      Description

      As an OpenIDM Administrator, I would like to be able to efficiently request information stored within managed objects which are related to the main managed object I am working with.

      When using the managed service to model complex relationships between entities, the need for efficiently viewing data across these entities is critical.

      For example, consider the out-of-the-box relationship between managed/users and managed/roles; this is a many-to-many relationship, whereby a user can have any number of managed/roles associated with it and a role can have any number of users associated with it.

      Consider these managed/role entries:

      [{
        "_id": "13425345345",
        "properties" : {
            "name": "Sales",
            "description": "People who work with customers"
        },
        "assignments": { ... }
      },
      {
        "_id": "455442331237",
        "properties" : {
           "name": "Engineering",
           "description": "People who work with software"
        },
        "assignments": { ... }
      }]
      

      The association between users and roles is maintained in the "roles" property of the managed/user, like so:

      {
        "_id": "wajih",
        "roles": [
           "managed/role/455442331237",
           "managed/role/13425345345"
         ]
      }
      

      Presently there is no way to make a request for managed/user/wajih that also includes the details for the roles that he is assigned. For example, a request that returns a response like so:

      {
        "userName": "wajih",
        "roles": [
           { 
              "_id": "managed/role/455442331237", 
              "properties": {
                 "name": "Sales",
                 "description": "People who work with software"
              }
           },
           { 
              "_id": "managed/role/13425345345", 
              "properties": {
                 "name": "Engineering",
                 "description": "People who work with customers"
              }
           }
         ]
      }
      

      Such an operation is conceptually very similar to a "join" query in a relational database. It is important that such operations can be performed as part of the request for the base object rather than as separate read requests for the related items, as it is possible that there are a large number of related items (which would make individual read calls for each one very costly in terms of performance).

      A join-type request as described above would have several uses. One is for a UI to edit the managed/user record - in this case, with a single request all of the data necessary to present the information would be available. At present, a separate request for each role assignment would be necessary.

      Another use could be during provisioning. The managed/user <-> managed/role relationship is not a good case for that, since it is unlikely that roles themselves would be provisioned. However, consider the case of managed/group <-> managed/user. It is very plausible that a user could desire to create a mapping to a mailing list system, whereby each managed/group translates into a particular mailing list. Imagine the managed/group records are structured like so:

      {
        "_id": "4534534",
        "name": "HR",
        "members" : [
          "managed/user/1234",
          "managed/user/2345",
          "managed/user/3456",
          "managed/user/4567"
        ]
      ]
      

      In your sync config, you may wish to map this group to the mailing list like so:

      {
        "name": "groupToMailingList",
        "source": "managed/group",
        "target": "system/mailinglist/list",
        "sourceQuery": {
            "_queryId": "query-all-ids",
            "_join": "members"
         }
        "properties" : [
          {
            "source": "name",
            "target": "listName"
          },
          {
            "source": "members",
            "target": "emailAddresses",
            "transform": {
              "type": "text/javascript",
              "source": "source.map(function (m) {return m.mail; }).join(',');"
            }
          }
         ]
      }
      

      This would work because the "_join" flag in the "sourceQuery" instructed the system to replace the values for "members" with the content from their related entities, in this case the "managed/user" records. Then within the transform the "mail" attribute is read out of each member and ultimately joined to produce a csv of all the email addresses for the members. Performing such a mapping without the use of a "join" operation in the backend would be much more tedious and have very poor performance, comparatively.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              brmiller Brendan Miller
              Reporter:
              jake.feasel Jake Feasel
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: