Skip to main content

Evolutions

Definition

As your business changes and your data model evolves with it, changes in your Knowledge Graph (KG) are inevitable. This could be due to simple renaming operations or more complex restructuring where you relocate attributes from one class to another.

However, these changes can disrupt the functionality of your existing dashboards by breaking widgets and shared answers. This is because they contain references to your KG attributes and classes, which can become stale or incorrect after modifications.

Evolutions in Veezoo serve to maintain the integrity of your dashboards by updating these references whenever there are changes in your KG. They act as a bridge that connects your old KG structure to the new one, ensuring that your widgets and shared answers continue to function correctly.

Creating Evolutions

Evolutions are necessary when you perform changes in your KG that could potentially disrupt your existing widgets or shared answers. They ensure that the references in these components are updated and aligned with the new KG structure.

For the following change, you do NOT need an evolution:

# Before
class Dim_Customer {
name: "Dim Customer"
...
}

# After
// Same identifier
class Dim_Customer {
// Name property changed for readability
name: "Customer"
}

For the following example, you need an evolution if you have dashboards that use it:

# Before
class Dim_Customer {
...
}

# After
// Identifier changed
class Customer {
...
}

In this example, you've changed the identifier of the class from Dim_Customer to Customer in your KG. Any widgets that reference Dim_Customer will break.

You will see an error message like this: Error loading widget: Could not find in the Knowledge Graph: kb.Dim_Customers

Breaking Change

To avoid this, you have to create an evolution step to update these references from Dim_Customer to Customer.

First, create an evolutions file in Studio, if you don't have one already:

Create File

To access the file next time, you will need to switch to the file view on the Sidebar and click on evolutions.

Evolutions Sidebar

This is the file that was created for you:

Empty Evolutions File

Now define evolutions by appending to the end of the list of evolution steps in the evolutions file:

evolutions {
evolution_list: [
// past evolutions
...,
// add at the end the new evolution
{
type: EvolutionType.Moving
from: "kb.Dim_Customer"
to: "kb.Customer"
}
]
}

Here, from: "kb.Dim_Customer" refers to the original class identifier, and to: "kb.Customer" refers to the new class identifier.

caution

The order of the evolution steps is critical, as they are applied sequentially!

Do NOT reorder, remove or modify past evolutions!

We plan to improve the UX for you to create evolutions in a more controlled way and validate the changes before applying. But for now use evolutions with caution and contact us, if you need help.

Evolution Types

Moving

The 'Moving' evolution type comes into play when you rename a resource or move an attribute to a different outer class. In our example, we changed the identifier from Dim_Customer to Customer. This operation would require a 'Moving' evolution.

The structure of a 'Moving' evolution is:

{
type: EvolutionType.Moving

from: "kb.Dim_Customer"

to: "kb.Customer"
}

Advanced: Moving across classes

In more complex scenarios where the attribute is being moved to a class that is connected via another class, the connection field is used.

Let's say you have the following state:

kb {
class Order {
...

// identifier is kb.Order.Product
class Product {
...
}

// identifier is kb.Order.Category
class Category {
...
}
}
}

Now, you may want to move Category inside Product to more accurately represent the business domain, as it is a product category, not an order category. This is how you modified it:

kb {
class Order {
...

// identifier is kb.Order.Product
class Product {
...

// identifier is now kb.Order.Product.Category
class Category {
...
}
}

}
}

To evolve all widgets accordingly, you will have to add the following evolution:

{
type: EvolutionType.Moving

from: "kb.Order.Category"

to: "kb.Order.Product.Category"

connection: [
"kb.Order.Product.relation", // this is an implicit relationship that connects Order to Product
"kb.Order.Product" // this is the end class
]
}

The connection field specifies the relationship-class path from the original domain ("Order") to the new domain ("Product"). This ensures that the references in your widgets and shared answers are updated correctly.

Remember, 'Moving' evolution does not physically alter the structure of your KG. It merely updates the references in your widgets and shared answers to reflect the new KG structure. The actual KG restructuring should be performed separately.

Advanced: Moving across classes over relationships

Let's build on top of the previous example with some slight modifications.

We start with the following state:

knowledge-base/classes/Order/class.vkl
kb {
class Order {
...

relationship with_Product {
to: kb.Product
sql: ...
}

// identifier is kb.Order.Category
class Category {
...
}
}
}

And another file for kb.Product.

knowledge-base/classes/Product/class.vkl
kb {
class Product {
...
}
}

Now, let's say the database schema changed and the information about Category is now in the Product table. This is how you modified the Knowledge Graph:

knowledge-base/classes/Order/class.vkl
kb {
class Order {
...

relationship with_Product {
to: kb.Product
sql: ...
}

// removed Category from inside here
}
}
knowledge-base/classes/Product/class.vkl
kb {
class Product {
...

// added it here
// the identifier is now kb.Product.Category
class Category {
...
}
}
}

To evolve all widgets accordingly, you will have to add the following evolution:

{
type: EvolutionType.Moving

from: "kb.Order.Category"

to: "kb.Product.Category"

connection: [
"kb.Order.with_Product", // this is the explicit relationship that connects Order to Product
"kb.Product" // this is the end class
]
}