Data Lens Table View
Last updated
Last updated
Note: These tools are in preview We follow a “dogfood” development approach—these tools are actively used and developed within our current WIP games. They are mature enough to share with our GitHub and Patreon supporters, so their documentation is provided here for early adopters.
The DataLensTableView
provides designers with a powerful, T-SQL-inspired query system to build dynamic views on game data. The key component driving this is the DataLens Query (FDataLensQuery
), which defines what data to select, filter, aggregate, and how to relate records.
This article fully documents how to write queries, especially focusing on the value expressions used in Select
, Where
, and aggregation clauses.
You will create your view derived from the UDataLensTableView
class, you can do this in Blueprint of in C++.
You will need to provide Class defaults for
Target Struct Type This is a USTRUCT that will be used to created the resulting TArray<YourStruct> and is what we reflect against to sort out your field data types.
Query This provides the configuration for what records to read from where and how to filter them and how to map them to your target struct type. We dive into the Query Structure below.
To Be Done
Views are "churned" by the Subsystem so you will need to "Register" the view with the subsystem for it to be processed at run time. More on this later.
The Get View Results node takes an input of your View, which you will get from the Subsystem and delivers an array of the struct type you provided, containing the resulting records. In C++ we have provided a templated function that does the same, more on that later.
FDataLensQuery
)InputAliases: Single related record attributes for quick reference by index [n]
.
RelatedAliases: Multi-related records for aggregate operations referenced as {n}
.
Select: Columns expressed as formulas using Input/Related aliases.
From: The main source table.
Join: Related tables joined.
WhereClause: Filtering expression
HavingClause: For future use, Grouping is only partly implemented later we "may" add full TSQL View like grouping, in which case this is part of that.
GroupBy: Grouping controls, grouping is only partially implemented at the moment and may be removed. We are "inspired" by TSQL's Create View, but we are not a relational DB, we are actually more similar to a Graph DB so we may strip it or change it entirely.
SortBy: Sorting controls.
FDataLensFieldAddress
)Source: Either the main source table (Query.From
) or a related record reference (a tag pointing to a related entity).
Attribute: The attribute/property to read from the Source
.
Source = "NPCTable.Rel.Faction"
— the related Faction record linked to the NPC.
Attribute = "FactionTable.Attr.Level"
— the Level attribute of that Faction.
FLensTableViewColumn
)Formula: the "expression" of how data should be mapped to this column
ColumnName: the name of the property in the struct provided to the view where the result should be written.
[n]
and {n}
[n]
Represent single related record attributes.
Indexed by their position in InputAliases
.
When used in expressions, [0]
refers to the first Input Alias.
Example:
If InputAliases[0] = { Source: NPCTable.Rel.Faction, Attribute: FactionTable.Attr.Level }
Then [0]
in expressions reads the Level of the NPC's Faction.
{n}
Represent collections of related records (e.g., multiple family members).
Indexed by their position in RelatedAliases
.
Used primarily in aggregate functions.
Example:
If RelatedAliases[0] = { Source: NPCTable.Rel.FamilyMembers, Attribute: NPCTable.Attr.Rank }
Then
Sum({0})
sums the Rank attribute of all family members.
CountIf({0}, > 2)
counts how many family members have Rank > 2.
[0] / 10
— reads attribute at InputAlias 0 and divides by 10 (e.g., health scaled to 2 decimals).
Sum({0}) + 1
— sums values of RelatedAlias 0 and adds 1.
SumIf({0}, > 3)
— sums values > 3 only.
[0] / 1000 >= 0.5
— true if attribute at InputAlias 0 is at least 50% of max (e.g., health check).
HasAny("Merchant", "ShopKeeper")
— true if the record has any of these traits.
TraitCount("Merchant") + TraitCount("ShopKeeper") > 1
True if the record has at least two of those traits.
InputAliases ([n]
) point to a single related record's attribute for direct access.
RelatedAliases ({n}
) point to multiple related records' attributes for aggregation.
Expressions combine these aliases with operators, aggregation functions (Sum
, CountIf
), and logical conditions to create flexible, designer-friendly data queries.
Aggregates only work on Related Record aliases, these are the Field Addresses you populated in the Related Aliases collection of the Query. {0} for example means to use the first index of the RelatedAliases Field Addresses.
Add up the values of the related expression.
Add up the values if they pass the condition
Find the average of values, e.g. Sum them all then divide by the number found. e.g. 5 entries with a total of 100 would be 20
Find the mean of the values, e.g. find the min and max, take the difference between the max-min and divide by 2 adding that to the min. thu,s min = 10 max = 30 would return ((30-10)/2)+10 = 20
Find the smallest value in the related
Find the largest value in the related
Count the number of records in the target related
Count the number of records in the target related if the condition is met
Get the value of the first record found in the related
Get the value of the last record found in the related
Trait functions operate on tags and check the tag against the record being tested. note the inputs must be the "Name" of a tag this system uses Unreal's built-in GameplayTag system.
The Name must be quoted, you can use either " or ' to quote e.g. "TagName"
or 'Tagname'
will work assuming TagName is the fully qualified name of a tag.
You can use , or whitespace to delineate tags in the HasAll and HasAny e.g. "TagName",'OtherTagName'
and "TagName" 'OtherTagName'
will work
This returns true if the trait is present on the record
This returns 0 if the trait is not present and 1 if it is. This is usually used to test if a record has "some" of a set of traits for example TraitCount(Sword) + TraitCount(Axe) + TraitCount(Spear) > 2
would be true if the record as 2 or more of Sword, Axe and Spear.
This returns true if any of the traits listed ar present.
This returns true if all the traits are present
These are operations that expect a value on the left and right side and perform basic math or logic operations. These work with Input Aliases such as [0]
, Aggregate results Sum({0})
, and Trait functions TraitCount("TagName")
, as well as constants of course 42
.
This lets you effect operation execution for example
This would solve the operations within the parins first then solve the resulting equation.
Find the sum of the equation
Find the difference of the equation
Find the product of the equation
Find the quotient of the equation
Return true if the left is greater than the right. This will return 1.0 or 0.0 for true and false when assigned to a numeric target or true and false when used in the where clause
Return true if the left is less than the right. This will return 1.0 or 0.0 for true and false when assigned to a numeric target or true and false when used in the where clause
Return true if the left is greater than or equal to the right. This will return 1.0 or 0.0 for true and false when assigned to a numeric target or true and false when used in the where clause
Return true if the left is less than or equal to the right. This will return 1.0 or 0.0 for true and false when assigned to a numeric target or true and false when used in the where clause
Return true if the left is equal to the right. This will return 1.0 or 0.0 for true and false when assigned to a numeric target or true and false when used in the where clause
Return true if the left is not equal to the right. This will return 1.0 or 0.0 for true and false when assigned to a numeric target or true and false when used in the where clause
Return true if the left and right are > 0. This will return 1.0 or 0.0 for true and false when assigned to a numeric target or true and false when used in the where clause
Return true if the left or right are > 0. This will return 1.0 or 0.0 for true and false when assigned to a numeric target or true and false when used in the where clause
Returns the negative of the right side e.g. "inverse"
Select expressions define the data or values returned by a query. Effectively, these are your "Column Mappings" mapping some evaluation's output to a target field in the provided USTRUCT.
The "Select" is an array of FLensTableViewColumn
, which defines a formula and a column name.
The above assumes the first Related Alias is reading the Age attribute a Family Members related records. Thus, it's returning the number of Family Members whose age is > 17.
The data type of the target column determines the output type of the formula and can be Boolean, Float or Int32. Behind the curtain, we store everything as an int, process everything as a float and perform the final write via static_cast. in the case of Boolean our internal rule is simply > 0 = true else false.
If you try to map to a USTRUCT field that is not Boolean, Float or Int it will simply be ignored as an invalid mapping. In the editor, we do warn you of this but we never break, thus we are modder-friendly.
Where expressions define the "filter" for records, the where clause is "inclusive" meaning a record will process the where expression and if the result is "true" the record is added to the available records to map; if its false the record is skipped.
You might use something like this to return a view of all the Character NPCs that are non-magic using class types.
Where Expressions do work with all operations, aggregates and trait functions. This is done via our "boolean" rule e.g. > 0 is true else false. That said you of course want to keep your where clause simple and fast making Traits the ideal aspect of a record to filter on.