Custom Fields in GoodData Cloud

This tutorial explains how to implement per-tenant custom fields in GoodData Cloud. This is especially useful in multi-tenant environments where each tenant has their own GoodData Workspace with data filtered by Workspace Data Filters (WDF). In such cases, tenants may need to extend the Logical Data Model (LDM) by adding custom fields.

Understanding the GoodData Cloud Environment

In GoodData Cloud, when workspaces are organized in a hierarchy, the LDM and its mappings are inherited by child workspaces. However, it is not possible to directly modify inherited datasets in child workspaces, meaning you cannot add, rename, or hide existing fields.

Fortunately, GoodData allows extending the inherited LDM by adding new datasets at the workspace level. Since inherited objects remain unchanged, all custom fields must be created in separate datasets within child workspaces.

Solution Overview

To implement custom fields per tenant, follow these steps:

  • Define core fields: Store all standard (core) fields in the parent workspace’s LDM datasets.

    • Define primary keys: Core datasets that can contain custom fields should have a defined primary key.
  • Extend the model in child workspaces: Add new datasets per entity in the child workspace to accommodate custom fields.

    • Create references: Link the extra dataset to the core dataset using the primary key with a many-to-many relationship (the bi-directional dashed arrow).

    • Define custom fields: Add attributes, facts, or date fields to the extra dataset as needed.

    • Map workspace data filters: Include extra dataset mappings and references to the Workspace Data Filter, if necessary.

    • Avoid ID conflicts: Ensure that IDs between the inherited and custom objects do not clash.

    • Use API for modifications: Changes to the LDM must be made via API calls since the visual modeler does not support direct modifications to child workspaces.

Example: Implementing Custom Fields

Consider a scenario where a parent workspace defines the “Babies CORE” dataset, which contains standard fields.

In a child workspace, an additional dataset, “Babies EXTRA”, is introduced to store custom fields specific to the tenant.

The connection between the two datasets is established using “Baby uid” as the primary key.

Screenshot of the LDM with both the Core and Extra datasets

API Calls for Custom Field Implementation

Once the core LDM is set up in the parent workspace, use the following API call to retrieve its structure:

GET /api/v1/layout/workspaces/{PARENT-WORKSPACE-ID}/logicalModel

If you have already set up a workspace hierarchy and defined WDFs, you can modify the child workspace and add a custom fields dataset. Only the modifications (EXTRA datasets) should be part of the API call’s payload, not the whole parent data model. To do so, use the following API call:

PUT /api/v1/layout/workspaces/{CHILD-WORKSPACE-ID}/logicalModel

Example Payload for Adding Custom Fields

{
  "ldm": {
    "datasets": [
      {
        "id": "babies_extra",
        "title": "Babies EXTRA",
        "attributes": [
          {
            "id": "babies_extra.baby_gender",
            "title": "EXTRA Baby gender",
            "sourceColumn": "baby_gender",
            "sourceColumnDataType": "STRING",
            "tags": ["Babies"]
          }
        ],
        "facts": [
          {
            "id": "babies_extra.baby_fact",
            "title": "EXTRA Baby Fact",
            "sourceColumn": "baby_fact",
            "sourceColumnDataType": "NUMERIC",
            "tags": ["Babies"]
          }
        ],
        "references": [
          {
            "identifier": {
              "id": "{CORE-DATASET-ID}",
              "type": "dataset"
            },
            "multivalue": true,
            "sources": [
              {
                "column": "baby_uid",
                "dataType": "STRING",
                "target": {
                  "id": "{CORE-DATASET-PK-ATTR-ID}",
                  "type": "attribute"
                }
              }
            ]
          }
        ],
        "workspaceDataFilterReferences": [
          {
            "filterColumn": "{WDF-MAPPED-COLUMN}",
            "filterColumnDataType": "STRING",
            "filterId": {
              "id": "{WDF-ID}",
              "type": "workspaceDataFilter"
            }
          }
        ]
      }
    ]
  }
}

Important Notes

  • Objects in both CORE and EXTRA datasets can share the same tags to appear in the same folder in the Analyze catalog.
  • Naming is flexible; CORE and EXTRA are used here for illustration purposes.
  • The many-to-many relationship enables filtering and slicing across datasets, but GoodData Cloud’s many-to-many limitations still apply.
  • Extra datasets can contain multiple records per core entity, so make sure to avoid double counting.
  • GoodData Cloud performs an INNER JOIN between CORE and EXTRA datasets. If a core record lacks a corresponding extra record, it may be excluded from calculations.
  • Even if the CORE and EXTRA datasets map to the same physical table, a database JOIN will still be performed.
  • A single EXTRA dataset per CORE entity is efficient unless a true many-to-many relationship is needed. If you needed to have many-to-many custom fields (i.e. “Baby Nickname” where each baby can have multiple nicknames), you would need a separate EXTRA dataset for each such field.
  • Custom fields can be modified by making another API call with a new dataset definition. However, removing objects that are in use (e.g., an attribute used in a metric or insight) might make those objects unusable.

Conclusion

By following this tutorial, you can successfully implement custom fields for tenants in GoodData Cloud while maintaining the integrity of the inherited LDM. This solution provides flexibility while ensuring data consistency across workspaces. Happy modeling!

For more detailed insights, refer to the GoodData Documentation.