Skip to main content

default_filter

Definition

A default_filter is a filter expression for a class that is applied by default if no conflicting filter was already explicitly asked for in a question.

With it you are able to model more accurately the language inside your company. An example is when we have subscriptions in the data, but it contains also cancelled ones. Yet, when people ask about subscriptions, they intuitively expect to see only "active" ones. With default_filter, you don't need to pass the burden to the user of remembering to ask for "active", while not limiting their experience, if asking for "inactive" subscriptions is also a common use case.

Whenever you set a default_filter, the users will see it clearly in the answer with the possibility to remove it by clicking on it.

Usage

Boolean Filter

Let's take the example above. We have a class kb.Subscription with a boolean is_Active. This is how you would define it, using the VQL (Veezoo Query Language) syntax:

kb {

class Subscription {

name.en: "Subscription"

...


default_filter: """
this.is_Active = true
"""

boolean is_Active { ... }

}

}

Notice the usage of this, which refers to the Subscription class.

What if you have two filters? Just create a list of all of them to create multiple independent default filters.

kb {

class Subscription {

name.en: "Subscription"

...


/* Create a list using [...] */
default_filter: [
"this.is_Active = true",
"this.is_Valid = true"
]

boolean is_Active { ... }

boolean is_Valid { ... }

}

}
info

We recommend you keep the default filters simple, and split them up into multiple filters instead of one big filter for the best experience. Combining multiple default filters into one filter will make them interact in unexpected ways. If the example above was a single default filter instead of two it would for example not add the active filter if a valid filter is already present.

Entity Filter

Now, maybe there is no is_Active flag, but rather a Status which can be 'Active'.

kb {

class Subscription {

name.en: "Subscription"

...

default_filter: """
this.Status = kb.Subscription.Status.Active # Tip: Let the Editor's Autocomplete help you find the right way to refer to the Status Active here
"""

/** This is a class Status with entities like kb.Status.Active. */
class Status { ... }

}

}

In this case, if you would ask "how many subscriptions per status", Veezoo is smart enough to know not to apply the default_filter.

For negations, do it like this:

default_filter: """
this.Status != kb.Subscription.Status.Cancelled
"""

Finally, maybe there are multiple statuses that you need to consider. For this case, we use a union:

default_filter: """
this.Status = union(kb.Subscription.Status.Active, kb.Subscription.Status.On_Hold)
"""

Numeric filters

Let's say instead that we want to keep only those subscriptions by default with a positive subscription amount.

default_filter: """
this.Amount > 0
"""

For numeric filters, we support: <, <=, > and >=. We also support numeric operators like *, +, / and -.

Filters across classes

What if we need to filter out subscriptions that have a inactive customer (according to a separate class and table)?

This is how the default filter would change:

kb {

class Subscription {
...

relationship from_Customer { ... }

default_filter: """
var c: kb.Customer # think of this like the following SQL: FROM customers c

this.from_Customer = c
c.is_Active = true
"""
}
}

This can be made shorter:

default_filter: """
this.from_Customer.is_Active = true
"""

Now, let's go a bit wild.

Let's say we have subscriptions and actual orders. And subscriptions should by default include only those with customers that had at least 2 orders at any point in time.

default_filter: """
var c: kb.Customer

# c is this subscription's customer
this.from_Customer = c

var o: kb.Order # these are orders from the same customer
o.from_Customer = c

# let's count these orders here for each customer
var number_of_orders = count(o) by c

# only those customers with at least 2 orders
number_of_orders >= 2
"""

Refactoring

Now this could get unnecessarily complicated and usually you will want to push certain definitions down to the data warehouse as part of your transformation layer (e.g. using dbt), especially if other applications or data consumers would benefit from it. This will allow you to have just a simple boolean flag and then we are back to the first example.

If for whatever reason you don't want to do so, you can also define a boolean in Veezoo with the code from your more complicated default_filter.

Let's take it from the last example:

kb {
class Subscription {

...

default_filter: "this.is_Active = true"

boolean is_Active {
name.en: "Active"

description.en:
"A subscription is active if it is from a customer that made at least two orders."

definition: """
var c: kb.Customer

# c is this subscription's customer
this.from_Customer = c

var o: kb.Order # these are orders from the same customer
o.from_Customer = c

# let's count these orders here for each customer
var number_of_orders = count(o) by c

# only those customers with at least 2 orders
number_of_orders >= 2
"""
}
}
}

Or better, defining it in the kb.Customer class.

kb {

class Customer {

...

default_filter: "this.is_Active = true"

boolean is_Active {
name.en: "Active"

description.en: "A customer that made at least two orders is deemed active."

definition: """
var o: kb.Order
o.from_Customer = this

var number_of_orders = count(o)
number_of_orders >= 2
"""
}
}
}

Now, you can define the default_filter for Subscription as simply:

kb {
class Subscription {
...

relationship from_Customer { ... }

default_filter: "this.from_Customer"
}
}

This may seem a bit less intuitive at first sight, but it means that the subscription has by default a customer set, which is itself by default active.

Ok, now that you know how to do all of this, remember the golden rule: Keep It Simple, Stupid.