Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto-expand transformation #293

Open
wants to merge 35 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
4750db8
auto-expand transformation
HeikoTheissen Nov 10, 2023
53368e3
Avoid EnumType
HeikoTheissen Nov 10, 2023
64e5ae7
Instance annotations for auto-expanded result sets
HeikoTheissen Nov 14, 2023
b5a6f34
Reprased definitions
HeikoTheissen Nov 14, 2023
9238702
SortOrder -> SortOrderType
HeikoTheissen Nov 14, 2023
34b5a64
Avoid <dt>
HeikoTheissen Nov 14, 2023
443f99c
After alignment with @uhlmannm
HeikoTheissen Nov 15, 2023
2fb8ff2
rephrasing
HeikoTheissen Nov 15, 2023
f5dea9f
Make `LeafLevel` mandatory
HeikoTheissen Nov 15, 2023
41b289a
Don't call out instance annotation
HeikoTheissen Feb 2, 2024
2df14e4
Merge remote-tracking branch 'origin/main' into auto-expand
HeikoTheissen Apr 4, 2024
defafdf
Allowed values for DrillState
HeikoTheissen Apr 8, 2024
8584dfe
Merge remote-tracking branch 'origin/main' into auto-expand
HeikoTheissen Apr 11, 2024
f27abe8
auto-refreshed
HeikoTheissen Apr 11, 2024
3ca799d
@uhlmannm's suggestion
HeikoTheissen Apr 12, 2024
92f1abd
Simplifications agreed in V4 table meeting
HeikoTheissen Apr 26, 2024
bb78f7d
Example request
HeikoTheissen Apr 26, 2024
4181573
Rephrased
HeikoTheissen Apr 26, 2024
b227e7f
Typos
HeikoTheissen Apr 26, 2024
e390b0c
@uhlmannm's comments
HeikoTheissen Apr 29, 2024
b9ecf4f
explained example
HeikoTheissen Apr 29, 2024
b587137
expand N levels
HeikoTheissen Apr 29, 2024
ae774a6
renamed type
HeikoTheissen Apr 29, 2024
3cb5082
typo
HeikoTheissen Apr 29, 2024
c9bbadf
more links
HeikoTheissen Apr 29, 2024
3e6379a
corrected LeavesCount, ResultEntriesCount
HeikoTheissen Apr 29, 2024
f98c999
example formatting
HeikoTheissen Apr 29, 2024
64f96eb
save lines
HeikoTheissen Apr 29, 2024
bc35559
round parentheses for in
HeikoTheissen Apr 29, 2024
9f24039
More elegance
HeikoTheissen Apr 29, 2024
8c7b80b
reword: deeper -> finer-grained
HeikoTheissen Apr 29, 2024
4dfd1c6
Sort order like Common.SortOrderType
HeikoTheissen May 2, 2024
5036eba
As agreed in meeting on 2024-05-24
HeikoTheissen May 24, 2024
192cc17
Explain D vs. A
HeikoTheissen May 24, 2024
fbe94b9
Merge remote-tracking branch 'origin/main' into auto-expand
HeikoTheissen Jul 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions vocabularies/Analytics.json
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,102 @@
"@[email protected]": "Adding a list of other terms that can be annotated to it.",
"@Validation.ApplicableTerms": ["Common.Label"]
}
},
"AutoExpand": [
{
"$Kind": "Function",
"$EntitySetPath": "InputSet",
"$IsBound": true,
"@Common.Experimental": true,
"@Core.IsSignature": true,
"@Core.Description": "`$apply` transformation that expands an unnamed leveled hierarchy with custom aggregation of certain properties",
"$Parameter": [
{
"$Name": "InputSet",
"$Collection": true,
"$Type": "Edm.EntityType",
"@Core.Description": "Entity set to be processed"
},
{
"$Name": "Levels",
"$Collection": true,
"$Type": "Analytics.AutoExpandLevel",
"@Core.Description": "Collection of aggregation levels forming a leveled hierarchy",
"@Core.LongDescription": "Each element in the collection defines the property names for one level.\n A property must not referenced by more than one level.\n The first element in the collection defines the property names of the coarsest level,\n the following elements define the property names of consecutively finer-grained aggregation levels.\n All referenced properties must be groupable."
},
{
"$Name": "ExpandLevel",
"$Type": "Edm.Int64",
"@Core.Description": "Number of levels to be expanded, counting from left",
"@Core.LongDescription": "The function result comprises the leveled hierarchy with the expanded levels and the following level as leaves in preorder."
},
{
"$Name": "Aggregation",
HeikoTheissen marked this conversation as resolved.
Show resolved Hide resolved
"$Collection": true,
"@Core.Description": "Properties to aggregate for all result entries on all levels",
"@Core.LongDescription": "All properties in this collection must be custom aggregates."
},
{
"$Name": "SiblingOrder",
"$Collection": true,
"$Type": "Analytics.AutoExpandSiblingOrder",
"@Core.Description": "Sort specification to apply to all direct descendants of a given entry in the resulting leveled hierarchy"
},
{
"$Name": "BeforeAggregationFilter",
"@Core.Description": "Expression valid for `filter` transformation to restrict the input set before any further procressing",
"@Core.OptionalParameter": {}
},
{
"$Name": "AggregatedValuesLeafFilter",
"@Core.Description": "Expression valid for `filter` transformation to restrict the input set at the most detailed grouping level with conditions on aggregated values",
"@Core.OptionalParameter": {}
},
{
"$Name": "Skip",
"$Type": "Edm.Int64",
"@Core.Description": "Number of entries to skip from the top of the fully ordered result",
"@Core.OptionalParameter": { "DefaultValue": "0" }
},
{
"$Name": "Top",
"$Type": "Edm.Int64",
"@Core.Description": "Number of entries to return from the result set after any skipping (absent means all)",
"@Core.OptionalParameter": {}
},
{
"$Name": "ResultEntriesCount",
"$Type": "Edm.Bool",
"@Core.Description": "Whether to return the total number of entries in the result independent of Skip/Top",
"@Core.OptionalParameter": { "DefaultValue": "false" }
}
],
"$ReturnType": { "$Collection": true, "$Type": "Edm.EntityType" }
Copy link
Member

@uhlmannm uhlmannm Nov 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the EntityType is not enough. We will need some of the information that we also get from a hierarchical query. Most importantly, the LimitedDescendantCount but also the DrillState and the DistanceFromRoot.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we need an instance annotation whose type contains a subset of the properties of Hierarchy.RecursiveHierarchyType. Which subset exactly?

Copy link
Member

@uhlmannm uhlmannm Nov 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ThomasChadzelek I had found the LimitedDescendantCount, the DrillState and the DistanceFromRoot. Is that it? Or already too much?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it sufficient if these instance annotations are returned by the auto-expand function? If one node is expanded, they must be computed by the OData model itself.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think yes. In the other cases, the model is creating requests to manually expand the visual groups. The backend would not even be aware that we are creating a visual grouping on the screen.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ThomasChadzelek I had found the LimitedDescendantCount, the DrillState and the DistanceFromRoot. Is that it? Or already too much?

What about LimitedRank? Our new favorite ;-)

DistanceFromRoot might be redundant because the hierarchy is leveled, not recursive?

}
],
"AutoExpandLevel": {
"$Kind": "ComplexType",
"@Common.Experimental": true,
"P": { "$Collection": true, "@Core.Description": "A non-empty set of property names constituting a level" }
HeikoTheissen marked this conversation as resolved.
Show resolved Hide resolved
},
"AutoExpandSiblingOrder": {
"$Kind": "ComplexType",
"@Common.Experimental": true,
"Property": { "@Core.Description": "Property by which to sort" },
"Order": {
"$Type": "Analytics.SortOrder",
"$DefaultValue": "Analytics.SortOrder/Asc",
"@Core.Description": "Sorting direction"
}
},
"SortOrder": {
"$Kind": "TypeDefinition",
"$UnderlyingType": "Edm.String",
"@Common.Experimental": true,
"@Validation.AllowedValues": [
{ "Value": "asc", "@Core.Description": "Sort in ascending order" },
{ "Value": "desc", "@Core.Description": "Sort in descending order" }
]
}
}
}
51 changes: 51 additions & 0 deletions vocabularies/Analytics.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,29 @@ Term|Type|Description
[AggregatedProperty](./Analytics.xml#L121:~:text=<Term%20Name="-,AggregatedProperty,-")|[AggregatedPropertyType](#AggregatedPropertyType)|<a name="AggregatedProperty"></a>Dynamic property for aggregate expression with specified aggregation method defined on the annotated entity type.
[AnalyticalContext](./Analytics.xml#L141:~:text=<Term%20Name="-,AnalyticalContext,-")|\[[AnalyticalContextType](#AnalyticalContextType)\]|<a name="AnalyticalContext"></a>Collection of properties that define an analytical context


## Functions

<a name="AutoExpand"></a>
### [AutoExpand](./Analytics.xml#L179:~:text=<Function%20Name="-,AutoExpand,-") *([Experimental](Common.md#Experimental))*

`$apply` transformation that expands an unnamed leveled hierarchy with custom aggregation of certain properties

Parameter|Type|Description
:--------|:---|:----------
**[InputSet](./Analytics.xml#L183:~:text=<Function%20Name="-,AutoExpand,-")**|\[EntityType\]|**Binding parameter:** Entity set to be processed
[Levels](./Analytics.xml#L186:~:text=<Function%20Name="-,AutoExpand,-")|\[[AutoExpandLevel](#AutoExpandLevel)\]|Collection of aggregation levels forming a leveled hierarchy<br>Each element in the collection defines the property names for one level. A property must not referenced by more than one level. The first element in the collection defines the property names of the coarsest level, the following elements define the property names of consecutively finer-grained aggregation levels. All referenced properties must be groupable.
[ExpandLevel](./Analytics.xml#L196:~:text=<Function%20Name="-,AutoExpand,-")|Int64|Number of levels to be expanded, counting from left<br>The function result comprises the leveled hierarchy with the expanded levels and the following level as leaves in preorder.
[Aggregation](./Analytics.xml#L202:~:text=<Function%20Name="-,AutoExpand,-")|\[String\]|Properties to aggregate for all result entries on all levels<br>All properties in this collection must be custom aggregates.
[SiblingOrder](./Analytics.xml#L208:~:text=<Function%20Name="-,AutoExpand,-")|\[[AutoExpandSiblingOrder](#AutoExpandSiblingOrder)\]|Sort specification to apply to all direct descendants of a given entry in the resulting leveled hierarchy
*[BeforeAggregationFilter](./Analytics.xml#L211:~:text=<Function%20Name="-,AutoExpand,-")*|String|*Optional parameter:* Expression valid for `filter` transformation to restrict the input set before any further procressing
*[AggregatedValuesLeafFilter](./Analytics.xml#L217:~:text=<Function%20Name="-,AutoExpand,-")*|String|*Optional parameter:* Expression valid for `filter` transformation to restrict the input set at the most detailed grouping level with conditions on aggregated values
*[Skip](./Analytics.xml#L223:~:text=<Function%20Name="-,AutoExpand,-")*|Int64|*Optional parameter:* Number of entries to skip from the top of the fully ordered result
*[Top](./Analytics.xml#L231:~:text=<Function%20Name="-,AutoExpand,-")*|Int64|*Optional parameter:* Number of entries to return from the result set after any skipping (absent means all)
*[ResultEntriesCount](./Analytics.xml#L237:~:text=<Function%20Name="-,AutoExpand,-")*|Bool|*Optional parameter:* Whether to return the total number of entries in the result independent of Skip/Top
[&rarr;](./Analytics.xml#L245:~:text=<Function%20Name="-,AutoExpand,-")|\[EntityType\]|


<a name="AggregatedPropertyType"></a>
## [AggregatedPropertyType](./Analytics.xml#L124:~:text=<ComplexType%20Name="-,AggregatedPropertyType,-")

Expand All @@ -43,3 +66,31 @@ Property|Type|Description
[Dimension](./Analytics.xml#L159:~:text=<ComplexType%20Name="-,AnalyticalContextType,-")|[Tag](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Tag)|The property holds the key of a dimension
[Measure](./Analytics.xml#L162:~:text=<ComplexType%20Name="-,AnalyticalContextType,-")|[Tag](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Tag)|The property holds the numeric value of a measure
[AccumulativeMeasure](./Analytics.xml#L165:~:text=<ComplexType%20Name="-,AnalyticalContextType,-")|[Tag](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Tag)|The measure has non-negative and additive values; it can be used in whole-part charts, e.g. the Donut

<a name="AutoExpandLevel"></a>
## [AutoExpandLevel](./Analytics.xml#L247:~:text=<ComplexType%20Name="-,AutoExpandLevel,-") *([Experimental](Common.md#Experimental))*


Property|Type|Description
:-------|:---|:----------
[P](./Analytics.xml#L249:~:text=<ComplexType%20Name="-,AutoExpandLevel,-")|\[String\]|A non-empty set of property names constituting a level

<a name="AutoExpandSiblingOrder"></a>
## [AutoExpandSiblingOrder](./Analytics.xml#L253:~:text=<ComplexType%20Name="-,AutoExpandSiblingOrder,-") *([Experimental](Common.md#Experimental))*


Property|Type|Description
:-------|:---|:----------
[Property](./Analytics.xml#L255:~:text=<ComplexType%20Name="-,AutoExpandSiblingOrder,-")|String|Property by which to sort
[Order](./Analytics.xml#L258:~:text=<ComplexType%20Name="-,AutoExpandSiblingOrder,-")|[SortOrder](#SortOrder)|Sorting direction

<a name="SortOrder"></a>
## [SortOrder](./Analytics.xml#L262:~:text=<TypeDefinition%20Name="-,SortOrder,-") *([Experimental](Common.md#Experimental))*
**Type:** String



Allowed Value|Description
:------------|:----------
[asc](./Analytics.xml#L266:~:text=<TypeDefinition%20Name="-,SortOrder,-")|Sort in ascending order
[desc](./Analytics.xml#L270:~:text=<TypeDefinition%20Name="-,SortOrder,-")|Sort in descending order
99 changes: 99 additions & 0 deletions vocabularies/Analytics.xml
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,105 @@
</Annotation>
</Annotations>

<Function Name="AutoExpand" IsBound="true" EntitySetPath="InputSet">
<Annotation Term="Common.Experimental" />
<Annotation Term="Core.IsSignature" />
<Annotation Term="Core.Description" String="`$apply` transformation that expands an unnamed leveled hierarchy with custom aggregation of certain properties" />
<Parameter Name="InputSet" Type="Collection(Edm.EntityType)" Nullable="false">
<Annotation Term="Core.Description" String="Entity set to be processed" />
</Parameter>
<Parameter Name="Levels" Type="Collection(Analytics.AutoExpandLevel)" Nullable="false">
<Annotation Term="Core.Description" String="Collection of aggregation levels forming a leveled hierarchy" />
<Annotation Term="Core.LongDescription">
<String>Each element in the collection defines the property names for one level.
A property must not referenced by more than one level.
The first element in the collection defines the property names of the coarsest level,
the following elements define the property names of consecutively finer-grained aggregation levels.
All referenced properties must be groupable.</String>
</Annotation>
</Parameter>
<Parameter Name="ExpandLevel" Type="Edm.Int64" Nullable="false">
<Annotation Term="Core.Description" String="Number of levels to be expanded, counting from left" />
<Annotation Term="Core.LongDescription">
<String>The function result comprises the leveled hierarchy with the expanded levels and the following level as leaves in preorder.</String>
</Annotation>
</Parameter>
<Parameter Name="Aggregation" Type="Collection(Edm.String)" Nullable="false">
<Annotation Term="Core.Description" String="Properties to aggregate for all result entries on all levels" />
<Annotation Term="Core.LongDescription">
<String>All properties in this collection must be custom aggregates.</String>
</Annotation>
</Parameter>
<Parameter Name="SiblingOrder" Type="Collection(Analytics.AutoExpandSiblingOrder)" Nullable="false">
<Annotation Term="Core.Description" String="Sort specification to apply to all direct descendants of a given entry in the resulting leveled hierarchy" />
</Parameter>
<Parameter Name="BeforeAggregationFilter" Type="Edm.String" Nullable="false">
<Annotation Term="Core.Description" String="Expression valid for `filter` transformation to restrict the input set before any further procressing" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't you achieve the same thing with a filter() transformation beforehand, in the same $apply? For TopLevels, we do likewise with orderby() or search() or filter().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but then the backend would have to take all these transformations together and process them as one "auto-expand" transformation. (At least with the Analytical Engine, the filter is part of the auto-expand operation.)

If the backend agrees, we can change this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the backend disagrees, do we need support for search as well? Or is that too fuzzy for analytics?

<Annotation Term="Core.OptionalParameter">
<Record/>
</Annotation>
</Parameter>
<Parameter Name="AggregatedValuesLeafFilter" Type="Edm.String" Nullable="false">
<Annotation Term="Core.Description" String="Expression valid for `filter` transformation to restrict the input set at the most detailed grouping level with conditions on aggregated values" />
<Annotation Term="Core.OptionalParameter">
<Record/>
</Annotation>
</Parameter>
<Parameter Name="Skip" Type="Edm.Int64" Nullable="false">
HeikoTheissen marked this conversation as resolved.
Show resolved Hide resolved
<Annotation Term="Core.Description" String="Number of entries to skip from the top of the fully ordered result" />
<Annotation Term="Core.OptionalParameter">
<Record>
<PropertyValue Property="DefaultValue" String="0" />
</Record>
</Annotation>
</Parameter>
<Parameter Name="Top" Type="Edm.Int64" Nullable="false">
<Annotation Term="Core.Description" String="Number of entries to return from the result set after any skipping (absent means all)" />
<Annotation Term="Core.OptionalParameter">
<Record/>
</Annotation>
</Parameter>
<Parameter Name="ResultEntriesCount" Type="Edm.Bool" Nullable="false">
<Annotation Term="Core.Description" String="Whether to return the total number of entries in the result independent of Skip/Top" />
<Annotation Term="Core.OptionalParameter">
<Record>
<PropertyValue Property="DefaultValue" String="false" />
</Record>
</Annotation>
</Parameter>
<ReturnType Type="Collection(Edm.EntityType)" />
</Function>
<ComplexType Name="AutoExpandLevel">
<Annotation Term="Common.Experimental" />
<Property Name="P" Type="Collection(Edm.String)" Nullable="false">
HeikoTheissen marked this conversation as resolved.
Show resolved Hide resolved
<Annotation Term="Core.Description" String="A non-empty set of property names constituting a level" />
</Property>
</ComplexType>
<ComplexType Name="AutoExpandSiblingOrder">
<Annotation Term="Common.Experimental" />
<Property Name="Property" Type="Edm.String" Nullable="false">
<Annotation Term="Core.Description" String="Property by which to sort" />
</Property>
<Property Name="Order" Type="Analytics.SortOrder" Nullable="false" DefaultValue="Analytics.SortOrder/Asc">
<Annotation Term="Core.Description" String="Sorting direction" />
</Property>
</ComplexType>
<TypeDefinition Name="SortOrder" UnderlyingType="Edm.String">
<Annotation Term="Common.Experimental" />
<Annotation Term="Validation.AllowedValues">
<Collection>
<Record>
<PropertyValue Property="Value" String="asc" />
<Annotation Term="Core.Description" String="Sort in ascending order" />
</Record>
<Record>
<PropertyValue Property="Value" String="desc" />
<Annotation Term="Core.Description" String="Sort in descending order" />
</Record>
</Collection>
</Annotation>
</TypeDefinition>

</Schema>
</edmx:DataServices>
</edmx:Edmx>