From 5d66d4dae05451032988a043c65d2f261fce4652 Mon Sep 17 00:00:00 2001
From: D024504 The term 2
segments ending in a primitive property. This path points to the
property holding the node identifier of the node in the hierarchy.
ParentNavigationProperty
allows navigation to the
-instance representing the parent node. It MUST be a nullable single- or
-collection-valued navigation property path that addresses the entity
-type annotated with this term.RecursiveHierarchy
can only be applied to
entity types, and MUST be applied with a qualifier, which is used to
@@ -3936,22 +3936,24 @@ 2
rolluprecursive
, and in hierarchy functions.
A node is an instance of an entity type annotated with
-RecursiveHierarchy
. It may have a parent node
-that is the target instance reached via the
-ParentNavigationProperty
. A
-recursive hierarchy
is a collection of such nodes with
+RecursiveHierarchy
and a given qualifier. The same entity
+can be different nodes, given different qualifiers. A node may have one
+or more parent nodes that are the target instances reached via
+the ParentNavigationProperty
. A recursive
+hierarchy for a given qualifier is a collection of such nodes with
unique node identifiers and no cycles in the traversal of parent
links.
A node without parent node is a root node, a node is a -child node of its parent node, a node without child nodes is a -leaf node. Nodes with the same parent node are sibling -nodes and so are root nodes. The descendants of a node are -its child nodes, their child nodes, and so on, up to and including all -leaf nodes that can be reached. A node together with its descendants -forms a sub-hierarchy of the hierarchy. The ancestors -of a node are its parent node, the parent of its parent node, and so on, -up to and including a root node that can be reached. A recursive -hierarchy can have one or more root nodes.
+A node without parent node or with null as parent node is a root +node, a node is a child node of its parent nodes, a node +without child nodes is a leaf node. Nodes with a common parent +node are sibling nodes and so are root nodes. The +descendants of a node are its child nodes, their child nodes, +and so on, up to and including all leaf nodes that can be reached. A +node together with its descendants forms a sub-hierarchy of the +hierarchy. The ancestors of a node are its parent nodes, the +parents of its parent nodes, and so on, up to and including root nodes +that can be reached. A recursive hierarchy can have one or more root +nodes.
The term UpNode
can be used in hierarchical result sets
to associate with each instance one of its ancestors, which is again
annotated with UpNode
and so on until a path to the root is
@@ -3991,7 +3993,7 @@
IncludeSelf
is true
issibling
tests if the given entity and another entity
(whose node identifier is given in a parameter Other
) have
-the same parent node or both are roots, but are not the sameisleaf
tests if the given entity is without
descendants.A recursive hierarchy organizes entities of a collection as nodes of
-one or more tree structures. This structure does not need to be as
-uniform as a leveled hierarchy. It is described by a complex term
-RecursiveHierarchy
with these properties:
A recursive hierarchy is defined on a collection of entities by +associating with every entity zero or more other entities from the same +collection, called its parents. The entities are called +nodes and each node within the collection must be identifiable +through a single primitive property called the node +identifier.
+A recursive hierarchy does not need to be as uniform as a leveled +hierarchy.
+The recursive hierarchy is described in the model by an annotation of
+the entity type with the complex term RecursiveHierarchy
+with these properties:
NodeProperty
contains a path with single-valued
segments ending in a primitive property. This path points to the
@@ -3927,22 +3934,17 @@ ParentNavigationProperty
allows navigation to the
instance or instances representing the parent nodes. It MUST be a
nullable single- or collection-valued navigation property path that
-addresses the entity type annotated with this term.The term RecursiveHierarchy
can only be applied to
entity types, and MUST be applied with a qualifier, which is used to
reference the hierarchy in transformations operating on recursive
hierarchies, in grouping with
rolluprecursive
, and in hierarchy functions.
A node is an instance of an entity type annotated with
-RecursiveHierarchy
and a given qualifier. The same entity
-can be different nodes, given different qualifiers. A node may have one
-or more parent nodes that are the target instances reached via
-the ParentNavigationProperty
. A recursive
-hierarchy for a given qualifier is a collection of such nodes with
-unique node identifiers and no cycles in the traversal of parent
-links.
A node without parent node or with null as parent node is a root
node, a node is a child node of its parent nodes, a node
without child nodes is a leaf node. Nodes with a common parent
diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
index 5218ba0bb..ff845efda 100644
--- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
+++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
@@ -2362,13 +2362,15 @@ The term `LeveledHierarchy` MUST be applied with a qualifier that can be used to
### 5.5.2 Recursive Hierarchy
-A recursive hierarchy organizes entities of a collection as nodes of one or more tree structures. This structure does not need to be as uniform as a leveled hierarchy. It is described by a complex term `RecursiveHierarchy` with these properties:
-- The `NodeProperty` contains a path with single-valued segments ending in a primitive property. This path points to the property holding the node identifier of the node in the hierarchy.
-- The `ParentNavigationProperty` allows navigation to the instance or instances representing the parent nodes. It MUST be a nullable single- or collection-valued navigation property path that addresses the entity type annotated with this term.
+A recursive hierarchy is defined on a collection of entities by associating with every entity zero or more other entities from the same collection, called its _parents_. The entities are called _nodes_ and each node within the collection must be identifiable through a single primitive property called the _node identifier_.
+
+A recursive hierarchy does not need to be as uniform as a leveled hierarchy.
-The term `RecursiveHierarchy` can only be applied to entity types, and MUST be applied with a qualifier, which is used to reference the hierarchy in transformations operating on recursive hierarchies, in [grouping with `rolluprecursive`](#Groupingwithrolluprecursive), and in [hierarchy functions](#HierarchyFunctions).
+The recursive hierarchy is described in the model by an annotation of the entity type with the complex term `RecursiveHierarchy` with these properties:
+- The `NodeProperty` contains a path with single-valued segments ending in a primitive property. This path points to the property holding the node identifier of the node in the hierarchy.
+- The `ParentNavigationProperty` allows navigation to the instance or instances representing the parent nodes. It MUST be a nullable single- or collection-valued navigation property path that addresses the entity type annotated with this term. There MUST NOT be any cycles in the traversal of parent links.
-A _node_ is an instance of an entity type annotated with `RecursiveHierarchy` and a given qualifier. The same entity can be different nodes, given different qualifiers. A node may have one or more _parent nodes_ that are the target instances reached via the `ParentNavigationProperty`. A _recursive hierarchy_ for a given qualifier is a collection of such nodes with unique node identifiers and no cycles in the traversal of parent links.
+The term `RecursiveHierarchy` can only be applied to entity types, and MUST be applied with a qualifier, which is used to reference the hierarchy in transformations operating on recursive hierarchies, in [grouping with `rolluprecursive`](#Groupingwithrolluprecursive), and in [hierarchy functions](#HierarchyFunctions). The same entity can serve as different nodes in different recursive hierarchies, given different qualifiers.
A node without parent node or with null as parent node is a _root node_, a node is a _child node_ of its parent nodes, a node without child nodes is a _leaf node_. Nodes with a common parent node are _sibling nodes_ and so are root nodes. The _descendants_ of a node are its child nodes, their child nodes, and so on, up to and including all leaf nodes that can be reached. A node together with its descendants forms a _sub-hierarchy_ of the hierarchy. The _ancestors_ of a node are its parent nodes, the parents of its parent nodes, and so on, up to and including root nodes that can be reached. A recursive hierarchy can have one or more root nodes.
diff --git a/odata-data-aggregation-ext/5 Vocabulary for Data Aggregation.md b/odata-data-aggregation-ext/5 Vocabulary for Data Aggregation.md
index 8653625cc..43989082e 100644
--- a/odata-data-aggregation-ext/5 Vocabulary for Data Aggregation.md
+++ b/odata-data-aggregation-ext/5 Vocabulary for Data Aggregation.md
@@ -165,13 +165,15 @@ The term `LeveledHierarchy` MUST be applied with a qualifier that can be used to
### ##subsubsec Recursive Hierarchy
-A recursive hierarchy organizes entities of a collection as nodes of one or more tree structures. This structure does not need to be as uniform as a leveled hierarchy. It is described by a complex term `RecursiveHierarchy` with these properties:
-- The `NodeProperty` contains a path with single-valued segments ending in a primitive property. This path points to the property holding the node identifier of the node in the hierarchy.
-- The `ParentNavigationProperty` allows navigation to the instance or instances representing the parent nodes. It MUST be a nullable single- or collection-valued navigation property path that addresses the entity type annotated with this term.
+A recursive hierarchy is defined on a collection of entities by associating with every entity zero or more other entities from the same collection, called its _parents_. The entities are called _nodes_ and each node within the collection must be identifiable through a single primitive property called the _node identifier_.
+
+A recursive hierarchy does not need to be as uniform as a leveled hierarchy.
-The term `RecursiveHierarchy` can only be applied to entity types, and MUST be applied with a qualifier, which is used to reference the hierarchy in transformations operating on recursive hierarchies, in [grouping with `rolluprecursive`](#Groupingwithrolluprecursive), and in [hierarchy functions](#HierarchyFunctions).
+The recursive hierarchy is described in the model by an annotation of the entity type with the complex term `RecursiveHierarchy` with these properties:
+- The `NodeProperty` contains a path with single-valued segments ending in a primitive property. This path points to the property holding the node identifier of the node in the hierarchy.
+- The `ParentNavigationProperty` allows navigation to the instance or instances representing the parent nodes. It MUST be a nullable single- or collection-valued navigation property path that addresses the entity type annotated with this term. There MUST NOT be any cycles in the traversal of parent links.
-A _node_ is an instance of an entity type annotated with `RecursiveHierarchy` and a given qualifier. The same entity can be different nodes, given different qualifiers. A node may have one or more _parent nodes_ that are the target instances reached via the `ParentNavigationProperty`. A _recursive hierarchy_ for a given qualifier is a collection of such nodes with unique node identifiers and no cycles in the traversal of parent links.
+The term `RecursiveHierarchy` can only be applied to entity types, and MUST be applied with a qualifier, which is used to reference the hierarchy in transformations operating on recursive hierarchies, in [grouping with `rolluprecursive`](#Groupingwithrolluprecursive), and in [hierarchy functions](#HierarchyFunctions). The same entity can serve as different nodes in different recursive hierarchies, given different qualifiers.
A node without parent node or with null as parent node is a _root node_, a node is a _child node_ of its parent nodes, a node without child nodes is a _leaf node_. Nodes with a common parent node are _sibling nodes_ and so are root nodes. The _descendants_ of a node are its child nodes, their child nodes, and so on, up to and including all leaf nodes that can be reached. A node together with its descendants forms a _sub-hierarchy_ of the hierarchy. The _ancestors_ of a node are its parent nodes, the parents of its parent nodes, and so on, up to and including root nodes that can be reached. A recursive hierarchy can have one or more root nodes.
From 23d69c84b01e01aea27b3831563979032987ea60 Mon Sep 17 00:00:00 2001
From: D024504 The term 2
property holding the node identifier of the node in the hierarchy.
ParentNavigationProperty
allows navigation to the
instance or instances representing the parent nodes. It MUST be a
-nullable single- or collection-valued navigation property path that
-addresses the entity type annotated with this term. There MUST NOT be
-any cycles in the traversal of parent links.RecursiveHierarchy
can only be applied to
entity types, and MUST be applied with a qualifier, which is used to
@@ -3945,17 +3945,16 @@ 2
href="#HierarchyFunctions">hierarchy functions. The same entity can
serve as different nodes in different recursive hierarchies, given
different qualifiers.
A node without parent node or with null as parent node is a root -node, a node is a child node of its parent nodes, a node -without child nodes is a leaf node. Nodes with a common parent -node are sibling nodes and so are root nodes. The -descendants of a node are its child nodes, their child nodes, -and so on, up to and including all leaf nodes that can be reached. A -node together with its descendants forms a sub-hierarchy of the -hierarchy. The ancestors of a node are its parent nodes, the -parents of its parent nodes, and so on, up to and including root nodes -that can be reached. A recursive hierarchy can have one or more root -nodes.
+A node without parent node is a root node, a node is a +child node of its parent nodes, a node without child nodes is a +leaf node. Two nodes with a common parent node are sibling +nodes and so are two root nodes. The descendants of a node +are its child nodes, their child nodes, and so on, up to and including +all leaf nodes that can be reached. A node together with its descendants +forms a sub-hierarchy of the hierarchy. The ancestors +of a node are its parent nodes, the parents of its parent nodes, and so +on, up to and including root nodes that can be reached. A recursive +hierarchy can have one or more root nodes.
The term UpNode
can be used in hierarchical result sets
to associate with each instance one of its ancestors, which is again
annotated with UpNode
and so on until a path to the root is
diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
index ff845efda..20b906c31 100644
--- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
+++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
@@ -2368,11 +2368,11 @@ A recursive hierarchy does not need to be as uniform as a leveled hierarchy.
The recursive hierarchy is described in the model by an annotation of the entity type with the complex term `RecursiveHierarchy` with these properties:
- The `NodeProperty` contains a path with single-valued segments ending in a primitive property. This path points to the property holding the node identifier of the node in the hierarchy.
-- The `ParentNavigationProperty` allows navigation to the instance or instances representing the parent nodes. It MUST be a nullable single- or collection-valued navigation property path that addresses the entity type annotated with this term. There MUST NOT be any cycles in the traversal of parent links.
+- The `ParentNavigationProperty` allows navigation to the instance or instances representing the parent nodes. It MUST be a collection-valued or nullable single-valued navigation property path that addresses the entity type annotated with this term. There MUST NOT be any cycles in the traversal of parent links.
The term `RecursiveHierarchy` can only be applied to entity types, and MUST be applied with a qualifier, which is used to reference the hierarchy in transformations operating on recursive hierarchies, in [grouping with `rolluprecursive`](#Groupingwithrolluprecursive), and in [hierarchy functions](#HierarchyFunctions). The same entity can serve as different nodes in different recursive hierarchies, given different qualifiers.
-A node without parent node or with null as parent node is a _root node_, a node is a _child node_ of its parent nodes, a node without child nodes is a _leaf node_. Nodes with a common parent node are _sibling nodes_ and so are root nodes. The _descendants_ of a node are its child nodes, their child nodes, and so on, up to and including all leaf nodes that can be reached. A node together with its descendants forms a _sub-hierarchy_ of the hierarchy. The _ancestors_ of a node are its parent nodes, the parents of its parent nodes, and so on, up to and including root nodes that can be reached. A recursive hierarchy can have one or more root nodes.
+A node without parent node is a _root node_, a node is a _child node_ of its parent nodes, a node without child nodes is a _leaf node_. Two nodes with a common parent node are _sibling nodes_ and so are two root nodes. The _descendants_ of a node are its child nodes, their child nodes, and so on, up to and including all leaf nodes that can be reached. A node together with its descendants forms a _sub-hierarchy_ of the hierarchy. The _ancestors_ of a node are its parent nodes, the parents of its parent nodes, and so on, up to and including root nodes that can be reached. A recursive hierarchy can have one or more root nodes.
The term `UpNode` can be used in hierarchical result sets to associate with each instance one of its ancestors, which is again annotated with `UpNode` and so on until a path to the root is constructed.
diff --git a/odata-data-aggregation-ext/5 Vocabulary for Data Aggregation.md b/odata-data-aggregation-ext/5 Vocabulary for Data Aggregation.md
index 43989082e..cd97fa110 100644
--- a/odata-data-aggregation-ext/5 Vocabulary for Data Aggregation.md
+++ b/odata-data-aggregation-ext/5 Vocabulary for Data Aggregation.md
@@ -171,11 +171,11 @@ A recursive hierarchy does not need to be as uniform as a leveled hierarchy.
The recursive hierarchy is described in the model by an annotation of the entity type with the complex term `RecursiveHierarchy` with these properties:
- The `NodeProperty` contains a path with single-valued segments ending in a primitive property. This path points to the property holding the node identifier of the node in the hierarchy.
-- The `ParentNavigationProperty` allows navigation to the instance or instances representing the parent nodes. It MUST be a nullable single- or collection-valued navigation property path that addresses the entity type annotated with this term. There MUST NOT be any cycles in the traversal of parent links.
+- The `ParentNavigationProperty` allows navigation to the instance or instances representing the parent nodes. It MUST be a collection-valued or nullable single-valued navigation property path that addresses the entity type annotated with this term. There MUST NOT be any cycles in the traversal of parent links.
The term `RecursiveHierarchy` can only be applied to entity types, and MUST be applied with a qualifier, which is used to reference the hierarchy in transformations operating on recursive hierarchies, in [grouping with `rolluprecursive`](#Groupingwithrolluprecursive), and in [hierarchy functions](#HierarchyFunctions). The same entity can serve as different nodes in different recursive hierarchies, given different qualifiers.
-A node without parent node or with null as parent node is a _root node_, a node is a _child node_ of its parent nodes, a node without child nodes is a _leaf node_. Nodes with a common parent node are _sibling nodes_ and so are root nodes. The _descendants_ of a node are its child nodes, their child nodes, and so on, up to and including all leaf nodes that can be reached. A node together with its descendants forms a _sub-hierarchy_ of the hierarchy. The _ancestors_ of a node are its parent nodes, the parents of its parent nodes, and so on, up to and including root nodes that can be reached. A recursive hierarchy can have one or more root nodes.
+A node without parent node is a _root node_, a node is a _child node_ of its parent nodes, a node without child nodes is a _leaf node_. Two nodes with a common parent node are _sibling nodes_ and so are two root nodes. The _descendants_ of a node are its child nodes, their child nodes, and so on, up to and including all leaf nodes that can be reached. A node together with its descendants forms a _sub-hierarchy_ of the hierarchy. The _ancestors_ of a node are its parent nodes, the parents of its parent nodes, and so on, up to and including root nodes that can be reached. A recursive hierarchy can have one or more root nodes.
The term `UpNode` can be used in hierarchical result sets to associate with each instance one of its ancestors, which is again annotated with `UpNode` and so on until a path to the root is constructed.
From 890b53b8f52d1ba59734ec7de0cbd7b827d02f3f Mon Sep 17 00:00:00 2001
From: D024504 2
href="#HierarchicalTransformationsPreservingtheInputSetStructure">Hierarchical
Transformations Preserving the Input Set Structure or be
service-defined bound functions whose output set is a subset of the
-input set.
NodeProperty
contains a path with single-valued
segments ending in a primitive property. This path points to the
-property holding the node identifier of the node in the hierarchy.ParentNavigationProperty
allows navigation to the
instance or instances representing the parent nodes. It MUST be a
collection-valued or nullable single-valued navigation property path
diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
index 4049b9c97..f7bbcc561 100644
--- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
+++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
@@ -2367,7 +2367,7 @@ A recursive hierarchy is defined on a collection of entities by associating with
A recursive hierarchy does not need to be as uniform as a leveled hierarchy.
The recursive hierarchy is described in the model by an annotation of the entity type with the complex term `RecursiveHierarchy` with these properties:
-- The `NodeProperty` contains a path with single-valued segments ending in a primitive property. This path points to the property holding the node identifier of the node in the hierarchy.
+- The `NodeProperty` contains a path with single-valued segments ending in a primitive property. This path points to the property holding the node identifier of the node in the hierarchy. Entities for which this path evaluates to null are not nodes of the hierarchy (sometimes called "orphans").
- The `ParentNavigationProperty` allows navigation to the instance or instances representing the parent nodes. It MUST be a collection-valued or nullable single-valued navigation property path that addresses the entity type annotated with this term. There MUST NOT be any cycles in the traversal of parent links.
The term `RecursiveHierarchy` can only be applied to entity types, and MUST be applied with a qualifier, which is used to reference the hierarchy in transformations operating on recursive hierarchies, in [grouping with `rolluprecursive`](#Groupingwithrolluprecursive), and in [hierarchy functions](#HierarchyFunctions). The same entity can serve as different nodes in different recursive hierarchies, given different qualifiers.
diff --git a/odata-data-aggregation-ext/5 Vocabulary for Data Aggregation.md b/odata-data-aggregation-ext/5 Vocabulary for Data Aggregation.md
index cd97fa110..b482e4e1e 100644
--- a/odata-data-aggregation-ext/5 Vocabulary for Data Aggregation.md
+++ b/odata-data-aggregation-ext/5 Vocabulary for Data Aggregation.md
@@ -170,7 +170,7 @@ A recursive hierarchy is defined on a collection of entities by associating with
A recursive hierarchy does not need to be as uniform as a leveled hierarchy.
The recursive hierarchy is described in the model by an annotation of the entity type with the complex term `RecursiveHierarchy` with these properties:
-- The `NodeProperty` contains a path with single-valued segments ending in a primitive property. This path points to the property holding the node identifier of the node in the hierarchy.
+- The `NodeProperty` contains a path with single-valued segments ending in a primitive property. This path points to the property holding the node identifier of the node in the hierarchy. Entities for which this path evaluates to null are not nodes of the hierarchy (sometimes called "orphans").
- The `ParentNavigationProperty` allows navigation to the instance or instances representing the parent nodes. It MUST be a collection-valued or nullable single-valued navigation property path that addresses the entity type annotated with this term. There MUST NOT be any cycles in the traversal of parent links.
The term `RecursiveHierarchy` can only be applied to entity types, and MUST be applied with a qualifier, which is used to reference the hierarchy in transformations operating on recursive hierarchies, in [grouping with `rolluprecursive`](#Groupingwithrolluprecursive), and in [hierarchy functions](#HierarchyFunctions). The same entity can serve as different nodes in different recursive hierarchies, given different qualifiers.
From b097c0a47363d87af05e2cc50d63f450672b27ac Mon Sep 17 00:00:00 2001
From: D024504 ParentNavigationProperty
allows navigation to the
instance or instances representing the parent nodes. It MUST be a
collection-valued or nullable single-valued navigation property path
-that addresses the entity type annotated with this term. There MUST NOT
-be any cycles in the traversal of parent links.The term results in results in results in Both examples result in The RecursiveHierarchy
can only be applied to
entity types, and MUST be applied with a qualifier, which is used to
diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
index f7bbcc561..1d4c18633 100644
--- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
+++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
@@ -2368,7 +2368,7 @@ A recursive hierarchy does not need to be as uniform as a leveled hierarchy.
The recursive hierarchy is described in the model by an annotation of the entity type with the complex term `RecursiveHierarchy` with these properties:
- The `NodeProperty` contains a path with single-valued segments ending in a primitive property. This path points to the property holding the node identifier of the node in the hierarchy. Entities for which this path evaluates to null are not nodes of the hierarchy (sometimes called "orphans").
-- The `ParentNavigationProperty` allows navigation to the instance or instances representing the parent nodes. It MUST be a collection-valued or nullable single-valued navigation property path that addresses the entity type annotated with this term. There MUST NOT be any cycles in the traversal of parent links.
+- The `ParentNavigationProperty` allows navigation to the instance or instances representing the parent nodes. It MUST be a collection-valued or nullable single-valued navigation property path that addresses the entity type annotated with this term. Nodes MUST NOT form cycles when following parent navigation properties.
The term `RecursiveHierarchy` can only be applied to entity types, and MUST be applied with a qualifier, which is used to reference the hierarchy in transformations operating on recursive hierarchies, in [grouping with `rolluprecursive`](#Groupingwithrolluprecursive), and in [hierarchy functions](#HierarchyFunctions). The same entity can serve as different nodes in different recursive hierarchies, given different qualifiers.
diff --git a/odata-data-aggregation-ext/5 Vocabulary for Data Aggregation.md b/odata-data-aggregation-ext/5 Vocabulary for Data Aggregation.md
index b482e4e1e..eead73780 100644
--- a/odata-data-aggregation-ext/5 Vocabulary for Data Aggregation.md
+++ b/odata-data-aggregation-ext/5 Vocabulary for Data Aggregation.md
@@ -171,7 +171,7 @@ A recursive hierarchy does not need to be as uniform as a leveled hierarchy.
The recursive hierarchy is described in the model by an annotation of the entity type with the complex term `RecursiveHierarchy` with these properties:
- The `NodeProperty` contains a path with single-valued segments ending in a primitive property. This path points to the property holding the node identifier of the node in the hierarchy. Entities for which this path evaluates to null are not nodes of the hierarchy (sometimes called "orphans").
-- The `ParentNavigationProperty` allows navigation to the instance or instances representing the parent nodes. It MUST be a collection-valued or nullable single-valued navigation property path that addresses the entity type annotated with this term. There MUST NOT be any cycles in the traversal of parent links.
+- The `ParentNavigationProperty` allows navigation to the instance or instances representing the parent nodes. It MUST be a collection-valued or nullable single-valued navigation property path that addresses the entity type annotated with this term. Nodes MUST NOT form cycles when following parent navigation properties.
The term `RecursiveHierarchy` can only be applied to entity types, and MUST be applied with a qualifier, which is used to reference the hierarchy in transformations operating on recursive hierarchies, in [grouping with `rolluprecursive`](#Groupingwithrolluprecursive), and in [hierarchy functions](#HierarchyFunctions). The same entity can serve as different nodes in different recursive hierarchies, given different qualifiers.
From 36323cc6bb63b5424eaf4499c2aeb64101a560cd Mon Sep 17 00:00:00 2001
From: D024504 3.2.1.2
{
-"@odata.context": "$metadata#Sales"
- "value": [
+ "@odata.context": "$metadata#Sales",
+ "value": [
{ "ID": 1, "Amount": 1 },
{ "ID": 7, "Amount": 1 }
]
@@ -3180,8 +3180,8 @@
3.2.1.2
{
-"@odata.context": "$metadata#Sales"
- "value": [
+ "@odata.context": "$metadata#Sales",
+ "value": [
{ "ID": 6, "Amount": 2 },
{ "ID": 7, "Amount": 1 }
]
@@ -3211,8 +3211,8 @@
3.2.1.2
{
-"@odata.context": "$metadata#Sales"
- "value": [
+ "@odata.context": "$metadata#Sales",
+ "value": [
{ "ID": 4, "Amount": 8 },
{ "ID": 5, "Amount": 4 }
]
@@ -3573,12 +3573,13 @@
3.2.1.2
GET /service/Products?$filter=Sales/any(s:s/Amount ge
Sales/aggregate(Amount with average) mul 2)
+{
- "@odata.context": "$metadata#Products",
- "value": [
- { "ID": "P3", "Name": "Paper", "Color": "White", "TaxRate": 0.14 }
- ]
-}
{
+"@odata.context": "$metadata#Products",
+ "value": [
+ { "ID": "P3", "Name": "Paper", "Color": "White", "TaxRate": 0.14 }
+ ]
+ }
3.5.2
@@ -5163,9 +5164,9 @@
7
{ "Customer": { "Name": "Joe", "ID": "C1" },
"Product": { "Name": "Paper" } },
{ "Customer": { "Name": "Joe", "ID": "C1" },
- "Product: { "Name": "Sugar" } },
- { "Customer": { "Name": "Sue", "ID": "C2" },
- "Product: { "Name": "Coffee"} },
+"Product": { "Name": "Sugar" } },
+ { "Customer": { "Name": "Sue", "ID": "C2" },
+ "Product": { "Name": "Coffee"} },
{ "Customer": { "Name": "Sue", "ID": "C2" },
"Product": { "Name": "Paper" } },
{ "Customer": { "Name": "Sue", "ID": "C3" },
@@ -5471,7 +5472,7 @@
7
}
aggregate
function can also be applied inside
-$apply:$apply
:
Example 82: Sales volume per customer in relation to total volume
GET /service/Sales?$apply=
@@ -5487,9 +5488,9 @@ 7
{ "Customer": { "@odata.id": "Customers('C1')" },
"Contribution@odata.type": "Decimal", "Contribution": 0.2916667 },
{ "Customer": { "@odata.id": "Customers('C2')" },
- "Contribution@odata.type": "Decimal", "Contribution": 0.5 } },
+ "Contribution@odata.type": "Decimal", "Contribution": 0.5 },
{ "Customer": { "@odata.id": "Customers('C3')" },
- "Contribution@odata.type": "Decimal", "Contribution": 0.2083333 } }
+ "Contribution@odata.type": "Decimal", "Contribution": 0.2083333 }
]
}
GET /service/Customers?$apply=outerjoin(Sales as ProductSales)
/groupby((Country,ProductSales/Product/Name))
returns the different combinations of products sold per country:
-{
- "@odata.context":"$metadata#Customers(Country,ProductSales())",
- "value": [
- { "Country": "Netherlands",
- "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
- "ProductSales": { "Product": { "Name": "Paper" } } },
- { "Country": "Netherlands",
- "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
- "ProductSales": { "Product": { "Name": "Sugar" } } },
- { "Country": "USA",
- "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
- "ProductSales": { "Product": { "Name": "Coffee" } } },
- { "Country": "USA",
- "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
- "ProductSales": { "Product": { "Name": "Paper" } } },
- { "Country": "USA",
- "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
- "ProductSales": { "Product": { "Name": "Sugar" } } },
- { "Country": "France", "ProductSales": null }
- ]
-}
+{
+"@odata.context":"$metadata#Customers(Country,ProductSales())",
+ "value": [
+ { "Country": "Netherlands",
+ "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
+ "ProductSales": { "Product": { "Name": "Paper" } } },
+ { "Country": "Netherlands",
+ "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
+ "ProductSales": { "Product": { "Name": "Sugar" } } },
+ { "Country": "USA",
+ "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
+ "ProductSales": { "Product": { "Name": "Coffee" } } },
+ { "Country": "USA",
+ "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
+ "ProductSales": { "Product": { "Name": "Paper" } } },
+ { "Country": "USA",
+ "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
+ "ProductSales": { "Product": { "Name": "Sugar" } } },
+ { "Country": "France", "ProductSales": null }
+ ]
+ }
Requesting Custom Aggregates Custom aggregates are defined through
the CustomAggregate
@@ -5807,15 +5809,16 @@
GET /service/Sales?$apply=groupby((Amount),aggregate(Amount with sum as Total))
will return all distinct amounts appearing in sales orders and how much money was made with deals of this amount
-{
- "@odata.context": "$metadata#Sales(Amount,Total)",
- "value": [
- { "Amount": 1, "Total@odata.type": "Decimal", "Total": 2 },
- { "Amount": 2, "Total@odata.type": "Decimal", "Total": 6 },
- { "Amount": 4, "Total@odata.type": "Decimal", "Total": 8 },
- { "Amount": 8, "Total@odata.type": "Decimal", "Total": 8 }
- ]
-}
+{
+"@odata.context": "$metadata#Sales(Amount,Total)",
+ "value": [
+ { "Amount": 1, "Total@odata.type": "Decimal", "Total": 2 },
+ { "Amount": 2, "Total@odata.type": "Decimal", "Total": 6 },
+ { "Amount": 4, "Total@odata.type": "Decimal", "Total": 8 },
+ { "Amount": 8, "Total@odata.type": "Decimal", "Total": 8 }
+ ]
+ }
per
property, no contradiction effectively
arises.
-{
- "@odata.context": "$metadata#Sales(*,per,Customer(ID),Product(ID))",
- "value": [
- { "Customer": { "ID": "C1" }, "Product": { "ID": "P2" },
- "ID": "3", "Amount": 4, "per": "Customer" },
- { "Customer": { "ID": "C2" }, "Product": { "ID": "P2" },
- "ID": "4", "Amount": 8, "per": "Customer" },
- { "Customer": { "ID": "C3" }, "Product": { "ID": "P1" },
- "ID": "6", "Amount": 2, "per": "Customer" },
- { "Customer": { "ID": "C3" }, "Product": { "ID": "P1" },
- "ID": "6", "Amount": 2, "per": "Product" },
- { "Customer": { "ID": "C2" }, "Product": { "ID": "P2" },
- "ID": "4", "Amount": 8, "per": "Product" },
- { "Customer": { "ID": "C2" }, "Product": { "ID": "P3" },
- "ID": "5", "Amount": 4, "per": "Product" }
- ]
-}
+{
+"@odata.context": "$metadata#Sales(*,per,Customer(ID),Product(ID))",
+ "value": [
+ { "Customer": { "ID": "C1" }, "Product": { "ID": "P2" },
+ "ID": "3", "Amount": 4, "per": "Customer" },
+ { "Customer": { "ID": "C2" }, "Product": { "ID": "P2" },
+ "ID": "4", "Amount": 8, "per": "Customer" },
+ { "Customer": { "ID": "C3" }, "Product": { "ID": "P1" },
+ "ID": "6", "Amount": 2, "per": "Customer" },
+ { "Customer": { "ID": "C3" }, "Product": { "ID": "P1" },
+ "ID": "6", "Amount": 2, "per": "Product" },
+ { "Customer": { "ID": "C2" }, "Product": { "ID": "P2" },
+ "ID": "4", "Amount": 8, "per": "Product" },
+ { "Customer": { "ID": "C2" }, "Product": { "ID": "P3" },
+ "ID": "5", "Amount": 4, "per": "Product" }
+ ]
+ }
The following non-exhaustive list contains variables that are used +throughout this document:
To this end, the following notation is used in the subsequent sections: If \(A\) is a collection and -\(v\) a data aggregation path, +\(p\) a data aggregation path, optionally followed by a type-cast segment, the result of such a path evaluation is denoted by \(\Gamma(A,v)\) and defined as the unordered +class="math inline">\(\Gamma(A,p)\) and defined as the unordered concatenation, possibly containing repetitions, of the collections \(γ(u,v)\) for each \(γ(u,p)\) for each \(u\) in \(A\) that is not null. The function \(γ(u,v)\) takes a non-null value and a path +class="math inline">\(γ(u,p)\) takes a non-null value and a path as arguments and is recursively defined as follows:
This notation is extended to the case of an empty path \(e\) by setting \(\Gamma(A,e)=A\). Note every \(u\) in \(\Gamma(A,v)\) occurs also in \(\Gamma(A,p)\) occurs also in \(A\) or nested into \(A\), therefore an algorithmic step like "Add a dynamic property to each \(u\) -in \(\Gamma(A,v)\)" effectively changes +in \(\Gamma(A,p)\)" effectively changes \(A\).
An aggregate expression MUST have one of the types listed below. To
compute the value of the property for a given aggregate expression, the
aggregate
transformation first determines a collection
-\(U\) of instances or primitive values,
+\(A\) of instances or primitive values,
based on the input set of the aggregate
transformation, and
a path \(p\) that occurs in the
aggregate expression. Let \(p_1\)
@@ -2160,7 +2162,7 @@
The property is a dynamic property, except for a special case in type @@ -2186,14 +2188,14 @@
CustomAggregate
annotation. The custom aggregate also
determines the type of the dynamic property.Determination of \(U\):
+Determination of \(A\):
Let \(I\) be the input set. If \(p\) is absent, let \(U=I\) with null values removed.
+class="math inline">\(A=I\) with null values removed.Otherwise, let \(q\) be the portion of \(p\) up to and including the last navigation property, if any, and any type-cast segment that immediately @@ -2253,8 +2255,8 @@
Then, if \(r\) is empty, let \(U=E\), otherwise let \(U=\Gamma(E,r)\), this consists of instances +class="math inline">\(A=E\), otherwise let \(A=\Gamma(E,r)\), this consists of instances or primitive values, possibly with repetitions.
as
outerjoin
, if \(U\) is empty, a null instance is added to
+class="math inline">\(A\) is empty, a null instance is added to
it.For each instance \(u\) in \(\Gamma(A,p_1/…/p_{k-1})\), let \(U=γ(u,p_k/q)\) and let the resource \(w\) be
+class="math inline">\(B=γ(u,p_k/q)\) and let the resource \(v\) beIf \(w\) is defined, then for each +
If \(v\) is defined, then for each transformation sequence, a dynamic property is added to \(u\) as follows: If \(p_k\) is a navigation property, the added @@ -3468,9 +3470,9 @@
Example 39:
GET /service/Customers?$apply=addnested(Sales,
@@ -4296,14 +4298,14 @@ 5.5
class="math inline">\(γ(u,p)\) reached via \(p\) starting from \(u\). Let \(p=p_1/…/p_k/s\) with \(p=p_1/…/p_k/r\) with \(k≥0\) be the concatenation where each
sub-path \(p_1,…,p_k\) consists of a
collection-valued segment that is optionally followed by a type-cast
segment and preceded by zero or more single-valued segments, and either
-\(s\) consists of one or more
+\(r\) consists of one or more
single-valued segments or \(k≥1\) and
-\({}/s\) is absent.
+\({}/r\) is absent.
The recursive hierarchy to be processed can also be a subset \(H'\) of \(H\). For this case a non-empty sequence
@@ -4403,7 +4405,7 @@
5.5
HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \quad {\tt
Node}=p,\;{\tt Ancestor}=u[p],\;{\tt MaxDistance}=d,\;{\tt
IncludeSelf}={\tt true})).\hfill }\]
-Otherwise \(p=p_1/…/p_k/s\) with
+
Otherwise \(p=p_1/…/p_k/r\) with
\(k≥1\), in this case the output set of
the transformation \(F(u)\) is defined
as the union of the output
@@ -4420,7 +4422,7 @@
5.5
Aggregation.isancestor}(\hfill\\ \hskip6pc {\tt
HierarchyNodes}=H',\;{\tt
HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \hskip6pc {\tt
-Node}=y_k/s,\;{\tt Descendant}=n,\;{\tt MaxDistance}=d,\;{\tt
+Node}=y_k/r,\;{\tt Descendant}=n,\;{\tt MaxDistance}=d,\;{\tt
IncludeSelf}={\tt true}\hfill\\ \hskip5pc )\hfill\\ \hskip4pc )\hfill\\
\hskip3pc ⋰\hfill\\ \hskip2pc )\hfill\\ \hskip1pc )\hfill\\ )\hfill
}\] or, for descendants
, 5.5
\hskip5pc \hbox{\tt Aggregation.isdescendant}(\hfill\\ \hskip6pc {\tt
HierarchyNodes}=H',\;{\tt
HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \hskip6pc {\tt
-Node}=y_k/s,\;{\tt Ancestor}=n,\;{\tt MaxDistance}=d,\;{\tt
+Node}=y_k/r,\;{\tt Ancestor}=n,\;{\tt MaxDistance}=d,\;{\tt
IncludeSelf}={\tt true}\hfill\\ \hskip5pc )\hfill\\ \hskip4pc )\hfill\\
\hskip3pc ⋰\hfill\\ \hskip2pc )\hfill\\ \hskip1pc )\hfill\\ )\hfill
}\] where \(y_1,…,y_k\) denote
lambdaVariableExpr
s and \({}/s\) may be absent.
+class="math inline">\({}/r\) may be absent.
If parameter \(d\) is absent, the
parameter \({\tt MaxDistance}=d\) is
omitted. If keep start
is absent, the parameter 5.5
If \(p\) contains only single-valued
segments, then \[F(x)={\tt filter}(p{\tt\ eq\
}x[q]).\]
-Otherwise \(p=p_1/…/p_k/s\) with
+
Otherwise \(p=p_1/…/p_k/r\) with
\(k≥1\) and \[\matrix{ F(x)={\tt filter}(\hfill\\ \hskip1pc
p_1/{\tt any}(y_1:\hfill\\ \hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\
\hskip3pc ⋱\hfill\\ \hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\
-\hskip5pc y_k/s{\tt\ eq\ }x[q]\hfill\\ \hskip4pc )\hfill\\ \hskip3pc
+\hskip5pc y_k/r{\tt\ eq\ }x[q]\hfill\\ \hskip4pc )\hfill\\ \hskip3pc
⋰\hfill\\ \hskip2pc )\hfill\\ \hskip1pc )\hfill\\ )\hfill }\]
where \(y_1,…,y_k\) denote
lambdaVariableExpr
s and \({}/s\) may be absent.
+class="math inline">\({}/r\) may be absent.
Example 60: Based on the SalesOrgHierarchy
defined in Hierarchy Examples
@@ -4883,7 +4885,7 @@ 5.5
HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \quad {\tt
Node}=p,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true})).\hfill
}\]
-Otherwise \(p=p_1/…/p_k/s\) with
+
Otherwise \(p=p_1/…/p_k/r\) with
\(k≥1\) and \[\matrix{ F(x)={\tt filter}(\hfill\\ \hskip1pc
p_1/{\tt any}(y_1:\hfill\\ \hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\
@@ -4891,12 +4893,12 @@ 5.5
\hskip5pc \hbox{\tt Aggregation.isdescendant}(\hfill\\ \hskip6pc {\tt
HierarchyNodes}=H',\;{\tt
HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \hskip6pc {\tt
-Node}=y_k/s,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true}\hfill\\
+Node}=y_k/r,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true}\hfill\\
\hskip5pc )\hfill\\ \hskip4pc )\hfill\\ \hskip3pc ⋰\hfill\\ \hskip2pc
)\hfill\\ \hskip1pc )\hfill\\ )\hfill }\]
where \(y_1,…,y_k\) denote
lambdaVariableExpr
s and \({}/s\) may be absent. (See \({}/r\) may be absent. (See example 108 for a case with \(k=1\).)
Non-normatively speaking, the effect of the algorithm can be
@@ -5247,7 +5249,7 @@
7
is \(I\) consisting of the pencil,
\(p=q/r={\tt Sales}/{\tt Amount}\),
\(E=\Gamma(I,q)\) is empty and \(U=\Gamma(E,r)\) is also empty. The sum over
+class="math inline">\(A=\Gamma(E,r)\) is also empty. The sum over
the empty collection is null.
@@ -6208,7 +6210,7 @@ 7.4
Example 107: Preorder
traversal of a hierarchy with 1:N relationship with collection-valued
segment \(p_1={\tt Sales}\) and \(s={\tt SalesOrganization}/{\tt ID}\).
+class="math inline">\(r={\tt SalesOrganization}/{\tt ID}\).
GET /service/Products?$apply=traverse(
$root/SalesOrganizations,
SalesOrgHierarchy,
diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
index ec75577a1..6f6b94e84 100644
--- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
+++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
@@ -211,15 +211,16 @@ This specification defines the following terms:
### 1.1.2 Acronyms and Abbreviations
-- $A,I,U$ – collections of instances
+The following non-exhaustive list contains variables that are used throughout this document:
+- $A,B,C$ – collections of instances
- $H$ – hierarchical collection
-- $u,w$ – instances in a collection
+- $u,v,w$ – instances in a collection
- $x,y$ – instances in a hierarchical collection, called nodes
-- $p,q,v$ – paths
+- $p,q,r$ – paths
- $S,T$ – transformation sequences
- $α$ – aggregate expression, defined [below](#AggregationAlgorithm)
-- $\Gamma(A,v)$ – the collection that results from evaluating a [data aggregation path](#DataAggregationPath) $v$ relative to a collection $A$, defined [below](#EvaluationofDataAggregationPaths)
-- $γ(u,v)$ – the collection that results from evaluating a [data aggregation path](#DataAggregationPath) $v$ relative to an instance $u$, defined [below](#EvaluationofDataAggregationPaths)
+- $\Gamma(A,p)$ – the collection that results from evaluating a [data aggregation path](#DataAggregationPath) $p$ relative to a collection $A$, defined [below](#EvaluationofDataAggregationPaths)
+- $γ(u,p)$ – the collection that results from evaluating a [data aggregation path](#DataAggregationPath) $p$ relative to an instance $u$, defined [below](#EvaluationofDataAggregationPaths)
- $\Pi_G(s)$ – a transformation of a collection that injects grouping properties into every instance of the collection, defined [below](#SimpleGrouping)
- $σ(x)$ – instance containing a grouping property that represents a node $x$, defined [below](#Transformationtraverse)
@@ -1082,18 +1083,18 @@ This document specifies when a [data aggregation path](#DataAggregationPath) tha
For a data aggregation path to be a common expression according to [OData-URL, section 5.1.1](#ODataURL), its segments must be single-valued with the possible exception of the last segment, and it can then be evaluated relative to an instance. For the transformations defined in this document, a data aggregation path can also be evaluated relative to a collection $A$, even if it has arbitrary collection-valued segments itself.
-To this end, the following notation is used in the subsequent sections: If $A$ is a collection and $v$ a data aggregation path, optionally followed by a type-cast segment, the result of such a path evaluation is denoted by $\Gamma(A,v)$ and defined as the unordered concatenation, possibly containing repetitions, of the collections $γ(u,v)$ for each $u$ in $A$ that is not null. The function $γ(u,v)$ takes a non-null value and a path as arguments and is recursively defined as follows:
-1. If $v$ is an empty path, let $B$ be a collection with $u$ as its single member and continue with step 9.
-2. Let $v_1$ be the first segment of $v$ and $v_2$ the remainder, if any, such that $v$ equals the concatenated path $v_1/v_2$.
-3. If $v_1$ is a type-cast segment and $u$ is of its type or a subtype thereof, let $w=u$ and continue with step 8.
-4. If $v_1$ is a type-cast segment and $u$ is not of its type or a subtype thereof, let $B$ be an empty collection and continue with step 9. (This rule follows [OData-URL, section 4.11](#ODataURL) rather than [OData-CSDL, section 14.4.1.1](#ODataCSDL).)
-5. Otherwise, $v_1$ is a non-type-cast segment. If $u$ does not contain a structural or navigation property $v_1$, let $B$ be an empty collection and continue with step 9.
-6. If $v_1$ is single-valued, let $w$ be the value of the structural or navigation property $v_1$ in $u$. If $w$ is null, let $B$ be an empty collection and continue with step 9; otherwise continue with step 8.
-7. Otherwise, $v_1$ is collection-valued. Let $C$ be the collection addressed by the structural or navigation property $v_1$ in $u$, and let $B=\Gamma(C,v_2)$. Then continue with step 9.
-8. Let $B=γ(w,v_2)$.
+To this end, the following notation is used in the subsequent sections: If $A$ is a collection and $p$ a data aggregation path, optionally followed by a type-cast segment, the result of such a path evaluation is denoted by $\Gamma(A,p)$ and defined as the unordered concatenation, possibly containing repetitions, of the collections $γ(u,p)$ for each $u$ in $A$ that is not null. The function $γ(u,p)$ takes a non-null value and a path as arguments and is recursively defined as follows:
+1. If $p$ is an empty path, let $B$ be a collection with $u$ as its single member and continue with step 9.
+2. Let $p_1$ be the first segment of $p$ and $p_2$ the remainder, if any, such that $p$ equals the concatenated path $p_1/p_2$.
+3. If $p_1$ is a type-cast segment and $u$ is of its type or a subtype thereof, let $v=u$ and continue with step 8.
+4. If $p_1$ is a type-cast segment and $u$ is not of its type or a subtype thereof, let $B$ be an empty collection and continue with step 9. (This rule follows [OData-URL, section 4.11](#ODataURL) rather than [OData-CSDL, section 14.4.1.1](#ODataCSDL).)
+5. Otherwise, $p_1$ is a non-type-cast segment. If $u$ does not contain a structural or navigation property $p_1$, let $B$ be an empty collection and continue with step 9.
+6. If $p_1$ is single-valued, let $v$ be the value of the structural or navigation property $p_1$ in $u$. If $v$ is null, let $B$ be an empty collection and continue with step 9; otherwise continue with step 8.
+7. Otherwise, $p_1$ is collection-valued. Let $C$ be the collection addressed by the structural or navigation property $p_1$ in $u$, and let $B=\Gamma(C,p_2)$. Then continue with step 9.
+8. Let $B=γ(v,p_2)$.
9. Return $B$.
-This notation is extended to the case of an empty path $e$ by setting $\Gamma(A,e)=A$. Note every $u$ in $\Gamma(A,v)$ occurs also in $A$ or nested into $A$, therefore an algorithmic step like "Add a dynamic property to each $u$ in $\Gamma(A,v)$" effectively changes $A$.
+This notation is extended to the case of an empty path $e$ by setting $\Gamma(A,e)=A$. Note every $u$ in $\Gamma(A,p)$ occurs also in $A$ or nested into $A$, therefore an algorithmic step like "Add a dynamic property to each $u$ in $\Gamma(A,p)$" effectively changes $A$.
## 3.2 Basic Aggregation
@@ -1103,29 +1104,29 @@ This notation is extended to the case of an empty path $e$ by setting $\Gamma(A,
The `aggregate` transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance of the [input type](#TypeStructureandContextURL) without entity-id containing one property per aggregate expression, representing the aggregated value of the input set.
-An aggregate expression MUST have one of the types listed below. To compute the value of the property for a given aggregate expression, the `aggregate` transformation first determines a collection $U$ of instances or primitive values, based on the input set of the `aggregate` transformation, and a path $p$ that occurs in the aggregate expression. Let $p_1$ denote a [data aggregation path](#DataAggregationPath) with single- or collection-valued segments and $p_2$ a type-cast segment. Depending on the type of aggregate expression, $p=p_1$ or $p=p_2$ or $p=p_1/p_2$. Each type of aggregate expression defines a function $f(U)$ which the aggregate transformation evaluates to obtain the property value.
+An aggregate expression MUST have one of the types listed below. To compute the value of the property for a given aggregate expression, the `aggregate` transformation first determines a collection $A$ of instances or primitive values, based on the input set of the `aggregate` transformation, and a path $p$ that occurs in the aggregate expression. Let $p_1$ denote a [data aggregation path](#DataAggregationPath) with single- or collection-valued segments and $p_2$ a type-cast segment. Depending on the type of aggregate expression, $p=p_1$ or $p=p_2$ or $p=p_1/p_2$. Each type of aggregate expression defines a function $f(A)$ which the aggregate transformation evaluates to obtain the property value.
The property is a dynamic property, except for a special case in type 4. In types 1 and 2, the aggregate expression MUST end with the keyword `with` and an aggregation method $g$. The aggregation method also determines the type of the dynamic property. In types 1, 2 and 3 the aggregate expression MUST, and in type 4 it MAY, be followed by the keyword [`as`](#Keywordas) and an [alias](#TypeStructureandContextURL), which is then the name of the dynamic property. More aggregate expressions can be constructed with the [`from`](#Keywordfrom) keyword, see later section.
_Types of aggregate expressions:_
1. A path $p=p_1$ or $p=p_1/p_2$ where the last segment of $p_1$ has a complex or entity or [aggregatable primitive type](#AggregatablePrimitiveType) whose values can be aggregated using the specified [aggregation method](#AggregationMethods) $g$, or $p=p_2$ if the input set can be aggregated using the [custom aggregation method](#CustomAggregationMethods) $g$.
-Let $f(U)=g(U)$.
+Let $f(A)=g(A)$.
2. An [aggregatable expression](#AggregatableExpression).
-Let $f(U)=g(V)$ where $V$ is the collection consisting of the aggregatable expression evaluated relative to each member of $U$ with null values removed from $V$. In this type, $p$ is absent.
+Let $f(A)=g(B)$ where $B$ is the collection consisting of the aggregatable expression evaluated relative to each member of $A$ with null values removed from $B$. In this type, $p$ is absent.
3. A path $p/{\tt\$count}$ (see [section 3.2.1.4](#AggregateExpressioncount)) with optional prefix $p/{}$ where $p=p_1$ or $p=p_2$ or $p=p_1/p_2$.
-Let $f(U)$ be the [cardinality](#SamenessandPrecedence) of $U$.
+Let $f(A)$ be the [cardinality](#SamenessandPrecedence) of $A$.
4. A path $p/c$ consisting of an optional prefix $p/{}$ with $p=p_1$ or $p=p_1/p_2$ where the last segment of $p_1$ has a structured type or $p=p_2$, and a [custom aggregate](#CustomAggregates) $c$ defined on the collection addressed by $p$.
-Let $f(U)=c(U)$, if computation of the custom aggregate fails, the service MUST reject the request. In the absence of an alias, the name of the property MUST be the name of the custom aggregate, this is a dynamic property unless there is a declared property with that name, which is allowed by the `CustomAggregate` annotation. The custom aggregate also determines the type of the dynamic property.
+Let $f(A)=c(A)$, if computation of the custom aggregate fails, the service MUST reject the request. In the absence of an alias, the name of the property MUST be the name of the custom aggregate, this is a dynamic property unless there is a declared property with that name, which is allowed by the `CustomAggregate` annotation. The custom aggregate also determines the type of the dynamic property.
-_Determination of $U$:_
+_Determination of $A$:_
-Let $I$ be the input set. If $p$ is absent, let $U=I$ with null values removed.
+Let $I$ be the input set. If $p$ is absent, let $A=I$ with null values removed.
Otherwise, let $q$ be the portion of $p$ up to and including the last navigation property, if any, and any type-cast segment that immediately follows, and let $r$ be the remainder, if any, of $p$ that contains no navigation properties, such that $p$ equals the concatenated path $q⁄r$. The aggregate transformation considers each entity reached via the path $q$ exactly once. To this end, using the [$\Gamma$ notation](#EvaluationofDataAggregationPaths):
- If $q$ is non-empty, let $E=\Gamma(I,q)$ and remove duplicates from that entity collection: If [multiple representations of the same non-transient entity](#SamenessandPrecedence) are reached, the service MUST merge them into one occurrence in $E$ if they are complementary and MUST reject the request if they are contradictory. (See [example 119](#aggrconflict).) If [multiple occurrences of the same transient entity](#SamenessandPrecedence) are reached, the service MUST keep only one occurrence in $E$.
- If $q$ is empty, let $E=I$.
-Then, if $r$ is empty, let $U=E$, otherwise let $U=\Gamma(E,r)$, this consists of instances or primitive values, possibly with repetitions.
+Then, if $r$ is empty, let $A=E$, otherwise let $A=\Gamma(E,r)$, this consists of instances or primitive values, possibly with repetitions.
#### 3.2.1.2 Keyword `as`
@@ -1426,12 +1427,12 @@ The algorithmic description of this transformation makes use of the following de
The output set of the groupby transformation is constructed in five steps.
1. [For each](#SamenessandPrecedence) instance $u$ in the input set, a projection is computed that contains only the grouping properties. This projection is $s_G(u,e)$ and the function $s_G(u,p)$ takes an instance and a path relative to the input set as arguments and is computed recursively as follows:
- - Let $w$ be an instance of the type of $u$ without properties and without entity-id.
+ - Let $v$ be an instance of the type of $u$ without properties and without entity-id.
- For each structural or navigation property $q$ of $u$:
- If $u$ has a subtype of the type addressed by $p$ and $q$ is only declared on that subtype, let $p'=p/p''/q$ where $p''$ is a type-cast to the subtype, otherwise let $p'=p/q$.
- - If $p'$ occurs in $G$, let $w[q]=u[q]$.
- - Otherwise, if $p'$ is a prefix of a path in $G$, let $w[q]=s_G(u[q],p')$.
- - Return $w$.
+ - If $p'$ occurs in $G$, let $v[q]=u[q]$.
+ - Otherwise, if $p'$ is a prefix of a path in $G$, let $v[q]=s_G(u[q],p')$.
+ - Return $v$.
2. The input set is split into subsets where two instances are in the same subset if their projections are [the same](#SamenessandPrecedence). If [representations of the same non-transient entity](#SamenessandPrecedence) are encountered during the comparison of two projections, the service MUST assign them to one subset with the merged representation if they are complementary and MUST reject the request if they are contradictory.
3. The set transformations from the second parameter are applied to each subset, resulting in a new set of potentially different structure and cardinality. Associated with each resulting set is the common projection of the instances in the subset from which the resulting set was computed.
4. Each set resulting from the previous step is transformed to contain the associated common projection $s$. This transformation is denoted by $\Pi_G(s)$ and is defined below.
@@ -1911,14 +1912,14 @@ results in
The `join` and `outerjoin` transformations take as their first parameter $p$ a collection-valued complex property or navigation property, optionally followed by a type-cast segment to address only instances of that derived type or one of its sub-types, followed by the `as` keyword, followed by an [alias](#TypeStructureandContextURL). The optional second parameter specifies a transformation sequence $T$.
[For each](#SamenessandPrecedence) instance $u$ in an [order-preserving loop](#SamenessandPrecedence) over the input set
-1. the instance collection $U$ addressed by $p$ is identified.
-2. If $T$ is provided, $U$ is replaced with the result of applying $T$ to $U$.
-3. In case of an `outerjoin`, if $U$ is empty, a null instance is added to it.
-4. [For each](#SamenessandPrecedence) instance $w$ in an [order-preserving loop](#SamenessandPrecedence) over $U$
- - an instance $x$ is appended to the output set of the transformation.
- - The instance $x$ is a clone of $u$ with an additional dynamic property whose name is the given alias and whose value is $w$.
- - The property $x$ is a navigation property if $p$ is a collection-valued navigation property, otherwise it is a complex property.
- - The property $x$ carries as control information the context URL of $u$.
+1. the instance collection $A$ addressed by $p$ is identified.
+2. If $T$ is provided, $A$ is replaced with the result of applying $T$ to $A$.
+3. In case of an `outerjoin`, if $A$ is empty, a null instance is added to it.
+4. [For each](#SamenessandPrecedence) instance $v$ in an [order-preserving loop](#SamenessandPrecedence) over $A$
+ - an instance $w$ is appended to the output set of the transformation.
+ - The instance $w$ is a clone of $u$ with an additional dynamic property whose name is the given alias and whose value is $v$.
+ - The property $w$ is a navigation property if $p$ is a collection-valued navigation property, otherwise it is a complex property.
+ - The property $w$ carries as control information the context URL of $u$.
::: example
Example 37: all links between products and sales instances
@@ -2006,12 +2007,12 @@ Further parameters are one or more transformation sequences followed by the as k
If $p_k$ is single-valued, the transformation sequences MUST consist of only `identity` or `compute` or `addnested` transformations, because these transform one-element collections into one-element collections. This makes it meaningful to speak (in this section only) of a transformation sequence applied to a single instance; this means applying it to a collection containing the single instance and taking as result the single instance from the output set.
-[For each](#SamenessandPrecedence) instance $u$ in $\Gamma(A,p_1/…/p_{k-1})$, let $U=γ(u,p_k/q)$ and let the resource $w$ be
-- the collection $U$ if $p_k$ is collection-valued
-- the single instance in $U$ if $p_k$ is single-valued and $U$ is non-empty
-- undefined if $p_k$ is single-valued and $U$ is empty.
+[For each](#SamenessandPrecedence) instance $u$ in $\Gamma(A,p_1/…/p_{k-1})$, let $B=γ(u,p_k/q)$ and let the resource $v$ be
+- the collection $B$ if $p_k$ is collection-valued
+- the single instance in $B$ if $p_k$ is single-valued and $B$ is non-empty
+- undefined if $p_k$ is single-valued and $B$ is empty.
-If $w$ is defined, then for each transformation sequence, a dynamic property is added to $u$ as follows: If $p_k$ is a navigation property, the added property is a dynamic navigation property, which is expanded by default, otherwise it is a dynamic structural property. Its name is the alias of the transformation sequence. The value of the added property is the result of the transformation sequence applied to $w$. The dynamic property carries as control information the context URL of $w$.
+If $v$ is defined, then for each transformation sequence, a dynamic property is added to $u$ as follows: If $p_k$ is a navigation property, the added property is a dynamic navigation property, which is expanded by default, otherwise it is a dynamic structural property. Its name is the alias of the transformation sequence. The value of the added property is the result of the transformation sequence applied to $v$. The dynamic property carries as control information the context URL of $v$.
::: example
Example 39:
@@ -2630,7 +2631,7 @@ The parameter lists defined in the following subsections have three mandatory pa
The recursive hierarchy is defined by a parameter pair $(H,Q)$, where $H$ and $Q$ MUST be specified as the first and second parameter. Here, $H$ MUST be an expression of type `Collection(Edm.EntityType)` starting with `$root` that has no multiple occurrences of the same entity. $H$ identifies the collection of node entities forming a recursive hierarchy based on an annotation of their common entity type with term `RecursiveHierarchy` with a `Qualifier` attribute whose value MUST be provided in $Q$. The property paths referenced by `NodeProperty` and `ParentNavigationProperty` in the `RecursiveHierarchy` annotation must be evaluable for the nodes in the recursive hierarchy, otherwise the service MUST reject the request. The `NodeProperty` is denoted by $q$ in this section.
-The third parameter MUST be a data aggregation path $p$ with single- or collection-valued segments whose last segment MUST be a primitive property. The node identifier(s) of an instance $u$ in the input set are the primitive values in $γ(u,p)$ reached via $p$ starting from $u$. Let $p=p_1/…/p_k/s$ with $k≥0$ be the concatenation where each sub-path $p_1,…,p_k$ consists of a collection-valued segment that is optionally followed by a type-cast segment and preceded by zero or more single-valued segments, and either $s$ consists of one or more single-valued segments or $k≥1$ and ${}/s$ is absent.
+The third parameter MUST be a data aggregation path $p$ with single- or collection-valued segments whose last segment MUST be a primitive property. The node identifier(s) of an instance $u$ in the input set are the primitive values in $γ(u,p)$ reached via $p$ starting from $u$. Let $p=p_1/…/p_k/r$ with $k≥0$ be the concatenation where each sub-path $p_1,…,p_k$ consists of a collection-valued segment that is optionally followed by a type-cast segment and preceded by zero or more single-valued segments, and either $r$ consists of one or more single-valued segments or $k≥1$ and ${}/r$ is absent.
The recursive hierarchy to be processed can also be a subset $H'$ of $H$. For this case a non-empty sequence $S$ of transformations MAY be specified as an optional parameter whose position varies from transformation to transformation and is given below. In general, let $H'$ be the output set of the transformation sequence $S$ applied to $H$, or $H'=H$ if $S$ is not specified. The transformations in $S$ MUST be listed in the section on [Transformations Preserving the Input Set Structure](#TransformationsPreservingtheInputSetStructure) or in the section on [Hierarchical Transformations Preserving the Input Set Structure](#HierarchicalTransformationsPreservingtheInputSetStructure) or be service-defined bound functions whose output set is a subset of the input set.
@@ -2661,13 +2662,13 @@ $$\matrix{ F(u)={\tt filter}(\hbox{\tt Aggregation.isancestor}(\hfill\\ \quad {\
or, for `descendants`,
$$\matrix{ F(u)={\tt filter}(\hbox{\tt Aggregation.isdescendant}(\hfill\\ \quad {\tt HierarchyNodes}=H',\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \quad {\tt Node}=p,\;{\tt Ancestor}=u[p],\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true})).\hfill }$$
-Otherwise $p=p_1/…/p_k/s$ with $k≥1$, in this case the output set of the transformation $F(u)$ is defined as the [union](#HierarchicalTransformations) of the output sets of transformations $G(n)$ applied to the input set for all $n$ in $γ(u,p)$. The output set of $G(n)$ consists of the instances of the input set whose node identifier is an ancestor or descendant of the node identifier $n$:
+Otherwise $p=p_1/…/p_k/r$ with $k≥1$, in this case the output set of the transformation $F(u)$ is defined as the [union](#HierarchicalTransformations) of the output sets of transformations $G(n)$ applied to the input set for all $n$ in $γ(u,p)$. The output set of $G(n)$ consists of the instances of the input set whose node identifier is an ancestor or descendant of the node identifier $n$:
For `ancestors`,
-$$\matrix{ G(n)={\tt filter}(\hfill\\ \hskip1pc p_1/{\tt any}(y_1:\hfill\\ \hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ \hskip3pc ⋱\hfill\\ \hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ \hskip5pc \hbox{\tt Aggregation.isancestor}(\hfill\\ \hskip6pc {\tt HierarchyNodes}=H',\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \hskip6pc {\tt Node}=y_k/s,\;{\tt Descendant}=n,\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}\hfill\\ \hskip5pc )\hfill\\ \hskip4pc )\hfill\\ \hskip3pc ⋰\hfill\\ \hskip2pc )\hfill\\ \hskip1pc )\hfill\\ )\hfill }$$
+$$\matrix{ G(n)={\tt filter}(\hfill\\ \hskip1pc p_1/{\tt any}(y_1:\hfill\\ \hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ \hskip3pc ⋱\hfill\\ \hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ \hskip5pc \hbox{\tt Aggregation.isancestor}(\hfill\\ \hskip6pc {\tt HierarchyNodes}=H',\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \hskip6pc {\tt Node}=y_k/r,\;{\tt Descendant}=n,\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}\hfill\\ \hskip5pc )\hfill\\ \hskip4pc )\hfill\\ \hskip3pc ⋰\hfill\\ \hskip2pc )\hfill\\ \hskip1pc )\hfill\\ )\hfill }$$
or, for `descendants`,
-$$\matrix{ G(n)={\tt filter}(\hfill\\ \hskip1pc p_1/{\tt any}(y_1:\hfill\\ \hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ \hskip3pc ⋱\hfill\\ \hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ \hskip5pc \hbox{\tt Aggregation.isdescendant}(\hfill\\ \hskip6pc {\tt HierarchyNodes}=H',\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \hskip6pc {\tt Node}=y_k/s,\;{\tt Ancestor}=n,\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}\hfill\\ \hskip5pc )\hfill\\ \hskip4pc )\hfill\\ \hskip3pc ⋰\hfill\\ \hskip2pc )\hfill\\ \hskip1pc )\hfill\\ )\hfill }$$
-where $y_1,…,y_k$ denote `lambdaVariableExpr`s and ${}/s$ may be absent.
+$$\matrix{ G(n)={\tt filter}(\hfill\\ \hskip1pc p_1/{\tt any}(y_1:\hfill\\ \hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ \hskip3pc ⋱\hfill\\ \hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ \hskip5pc \hbox{\tt Aggregation.isdescendant}(\hfill\\ \hskip6pc {\tt HierarchyNodes}=H',\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \hskip6pc {\tt Node}=y_k/r,\;{\tt Ancestor}=n,\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}\hfill\\ \hskip5pc )\hfill\\ \hskip4pc )\hfill\\ \hskip3pc ⋰\hfill\\ \hskip2pc )\hfill\\ \hskip1pc )\hfill\\ )\hfill }$$
+where $y_1,…,y_k$ denote `lambdaVariableExpr`s and ${}/r$ may be absent.
If parameter $d$ is absent, the parameter ${\tt MaxDistance}=d$ is omitted. If `keep start` is absent, the parameter ${\tt IncludeSelf}={\tt true}$ is omitted.
@@ -2807,9 +2808,9 @@ $F(x)$ is a transformation that determines for the specified node $x$ the instan
If $p$ contains only single-valued segments, then
$$F(x)={\tt filter}(p{\tt\ eq\ }x[q]).$$
-Otherwise $p=p_1/…/p_k/s$ with $k≥1$ and
-$$\matrix{ F(x)={\tt filter}(\hfill\\ \hskip1pc p_1/{\tt any}(y_1:\hfill\\ \hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ \hskip3pc ⋱\hfill\\ \hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ \hskip5pc y_k/s{\tt\ eq\ }x[q]\hfill\\ \hskip4pc )\hfill\\ \hskip3pc ⋰\hfill\\ \hskip2pc )\hfill\\ \hskip1pc )\hfill\\ )\hfill }$$
-where $y_1,…,y_k$ denote `lambdaVariableExpr`s and ${}/s$ may be absent.
+Otherwise $p=p_1/…/p_k/r$ with $k≥1$ and
+$$\matrix{ F(x)={\tt filter}(\hfill\\ \hskip1pc p_1/{\tt any}(y_1:\hfill\\ \hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ \hskip3pc ⋱\hfill\\ \hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ \hskip5pc y_k/r{\tt\ eq\ }x[q]\hfill\\ \hskip4pc )\hfill\\ \hskip3pc ⋰\hfill\\ \hskip2pc )\hfill\\ \hskip1pc )\hfill\\ )\hfill }$$
+where $y_1,…,y_k$ denote `lambdaVariableExpr`s and ${}/r$ may be absent.
::: example
Example 60: Based on the `SalesOrgHierarchy` defined in [Hierarchy Examples](#HierarchyExamples)
@@ -2888,9 +2889,9 @@ $$\matrix{ R(x)={\tt concat}(\hfill\\ \quad F(x)/{\tt compute}(x{\tt\ as\ }χ_N)
$F(x)$ is defined as follows: If $p$ contains only single-valued segments, then
$$\matrix{ F(x)={\tt filter}(\hbox{\tt Aggregation.isdescendant}(\hfill\\ \quad {\tt HierarchyNodes}=H',\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \quad {\tt Node}=p,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true})).\hfill }$$
-Otherwise $p=p_1/…/p_k/s$ with $k≥1$ and
-$$\matrix{ F(x)={\tt filter}(\hfill\\ \hskip1pc p_1/{\tt any}(y_1:\hfill\\ \hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ \hskip3pc ⋱\hfill\\ \hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ \hskip5pc \hbox{\tt Aggregation.isdescendant}(\hfill\\ \hskip6pc {\tt HierarchyNodes}=H',\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \hskip6pc {\tt Node}=y_k/s,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true}\hfill\\ \hskip5pc )\hfill\\ \hskip4pc )\hfill\\ \hskip3pc ⋰\hfill\\ \hskip2pc )\hfill\\ \hskip1pc )\hfill\\ )\hfill }$$
-where $y_1,…,y_k$ denote `lambdaVariableExpr`s and ${}/s$ may be absent. (See [example 108](#rollupcoll) for a case with $k=1$.)
+Otherwise $p=p_1/…/p_k/r$ with $k≥1$ and
+$$\matrix{ F(x)={\tt filter}(\hfill\\ \hskip1pc p_1/{\tt any}(y_1:\hfill\\ \hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ \hskip3pc ⋱\hfill\\ \hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ \hskip5pc \hbox{\tt Aggregation.isdescendant}(\hfill\\ \hskip6pc {\tt HierarchyNodes}=H',\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \hskip6pc {\tt Node}=y_k/r,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true}\hfill\\ \hskip5pc )\hfill\\ \hskip4pc )\hfill\\ \hskip3pc ⋰\hfill\\ \hskip2pc )\hfill\\ \hskip1pc )\hfill\\ )\hfill }$$
+where $y_1,…,y_k$ denote `lambdaVariableExpr`s and ${}/r$ may be absent. (See [example 108](#rollupcoll) for a case with $k=1$.)
Non-normatively speaking, the effect of the algorithm can be summarized as follows: If $M≥1$ and $\hat F_N(x)$ denotes the collection of all instances that are related to a node $x$ from the recursive hierarchy of the $N$-th `rolluprecursive` operator, then $T$ is applied to each of the intersections of $\hat F_1(χ_1),…,\hat F_M(χ_M)$, as $χ_N$ runs over all nodes of the $N$-th recursive hierarchy for $1≤N≤M$. Into the instances of the resulting output sets the $\Pi_G$ transformations inject information about the nodes $χ_1,…,χ_M$.
@@ -3188,7 +3189,7 @@ results in
}
```
-Note that the base set of the request is `Products`, so there is a result item for product `Pencil` even though there are no sales items. The input set for the aggregation in the third row is $I$ consisting of the pencil, $p=q/r={\tt Sales}/{\tt Amount}$, $E=\Gamma(I,q)$ is empty and $U=\Gamma(E,r)$ is also empty. The sum over the empty collection is null.
+Note that the base set of the request is `Products`, so there is a result item for product `Pencil` even though there are no sales items. The input set for the aggregation in the third row is $I$ consisting of the pencil, $p=q/r={\tt Sales}/{\tt Amount}$, $E=\Gamma(I,q)$ is empty and $A=\Gamma(E,r)$ is also empty. The sum over the empty collection is null.
:::
::: example
@@ -4210,7 +4211,7 @@ results in
:::
::: example
-Example 107: Preorder traversal of a hierarchy with 1:N relationship with collection-valued segment $p_1={\tt Sales}$ and $s={\tt SalesOrganization}/{\tt ID}$.
+Example 107: Preorder traversal of a hierarchy with 1:N relationship with collection-valued segment $p_1={\tt Sales}$ and $r={\tt SalesOrganization}/{\tt ID}$.
```
GET /service/Products?$apply=traverse(
$root/SalesOrganizations,
diff --git a/odata-data-aggregation-ext/1 Introduction.md b/odata-data-aggregation-ext/1 Introduction.md
index 42d08a0e0..4705ebf80 100644
--- a/odata-data-aggregation-ext/1 Introduction.md
+++ b/odata-data-aggregation-ext/1 Introduction.md
@@ -20,15 +20,16 @@ This specification defines the following terms:
### ##subsubsec Acronyms and Abbreviations
-- $A,I,U$ – collections of instances
+The following non-exhaustive list contains variables that are used throughout this document:
+- $A,B,C$ – collections of instances
- $H$ – hierarchical collection
-- $u,w$ – instances in a collection
+- $u,v,w$ – instances in a collection
- $x,y$ – instances in a hierarchical collection, called nodes
-- $p,q,v$ – paths
+- $p,q,r$ – paths
- $S,T$ – transformation sequences
- $α$ – aggregate expression, defined [below](#AggregationAlgorithm)
-- $\Gamma(A,v)$ – the collection that results from evaluating a [data aggregation path](#DataAggregationPath) $v$ relative to a collection $A$, defined [below](#EvaluationofDataAggregationPaths)
-- $γ(u,v)$ – the collection that results from evaluating a [data aggregation path](#DataAggregationPath) $v$ relative to an instance $u$, defined [below](#EvaluationofDataAggregationPaths)
+- $\Gamma(A,p)$ – the collection that results from evaluating a [data aggregation path](#DataAggregationPath) $p$ relative to a collection $A$, defined [below](#EvaluationofDataAggregationPaths)
+- $γ(u,p)$ – the collection that results from evaluating a [data aggregation path](#DataAggregationPath) $p$ relative to an instance $u$, defined [below](#EvaluationofDataAggregationPaths)
- $\Pi_G(s)$ – a transformation of a collection that injects grouping properties into every instance of the collection, defined [below](#SimpleGrouping)
- $σ(x)$ – instance containing a grouping property that represents a node $x$, defined [below](#Transformationtraverse)
diff --git a/odata-data-aggregation-ext/3.1 Fundamentals of Input and Output Sets.md b/odata-data-aggregation-ext/3.1 Fundamentals of Input and Output Sets.md
index 63eb88adf..f31994040 100644
--- a/odata-data-aggregation-ext/3.1 Fundamentals of Input and Output Sets.md
+++ b/odata-data-aggregation-ext/3.1 Fundamentals of Input and Output Sets.md
@@ -95,15 +95,15 @@ This document specifies when a [data aggregation path](#DataAggregationPath) tha
For a data aggregation path to be a common expression according to [OData-URL, section 5.1.1](#ODataURL), its segments must be single-valued with the possible exception of the last segment, and it can then be evaluated relative to an instance. For the transformations defined in this document, a data aggregation path can also be evaluated relative to a collection $A$, even if it has arbitrary collection-valued segments itself.
-To this end, the following notation is used in the subsequent sections: If $A$ is a collection and $v$ a data aggregation path, optionally followed by a type-cast segment, the result of such a path evaluation is denoted by $\Gamma(A,v)$ and defined as the unordered concatenation, possibly containing repetitions, of the collections $γ(u,v)$ for each $u$ in $A$ that is not null. The function $γ(u,v)$ takes a non-null value and a path as arguments and is recursively defined as follows:
-1. If $v$ is an empty path, let $B$ be a collection with $u$ as its single member and continue with step 9.
-2. Let $v_1$ be the first segment of $v$ and $v_2$ the remainder, if any, such that $v$ equals the concatenated path $v_1/v_2$.
-3. If $v_1$ is a type-cast segment and $u$ is of its type or a subtype thereof, let $w=u$ and continue with step 8.
-4. If $v_1$ is a type-cast segment and $u$ is not of its type or a subtype thereof, let $B$ be an empty collection and continue with step 9. (This rule follows [OData-URL, section 4.11](#ODataURL) rather than [OData-CSDL, section 14.4.1.1](#ODataCSDL).)
-5. Otherwise, $v_1$ is a non-type-cast segment. If $u$ does not contain a structural or navigation property $v_1$, let $B$ be an empty collection and continue with step 9.
-6. If $v_1$ is single-valued, let $w$ be the value of the structural or navigation property $v_1$ in $u$. If $w$ is null, let $B$ be an empty collection and continue with step 9; otherwise continue with step 8.
-7. Otherwise, $v_1$ is collection-valued. Let $C$ be the collection addressed by the structural or navigation property $v_1$ in $u$, and let $B=\Gamma(C,v_2)$. Then continue with step 9.
-8. Let $B=γ(w,v_2)$.
+To this end, the following notation is used in the subsequent sections: If $A$ is a collection and $p$ a data aggregation path, optionally followed by a type-cast segment, the result of such a path evaluation is denoted by $\Gamma(A,p)$ and defined as the unordered concatenation, possibly containing repetitions, of the collections $γ(u,p)$ for each $u$ in $A$ that is not null. The function $γ(u,p)$ takes a non-null value and a path as arguments and is recursively defined as follows:
+1. If $p$ is an empty path, let $B$ be a collection with $u$ as its single member and continue with step 9.
+2. Let $p_1$ be the first segment of $p$ and $p_2$ the remainder, if any, such that $p$ equals the concatenated path $p_1/p_2$.
+3. If $p_1$ is a type-cast segment and $u$ is of its type or a subtype thereof, let $v=u$ and continue with step 8.
+4. If $p_1$ is a type-cast segment and $u$ is not of its type or a subtype thereof, let $B$ be an empty collection and continue with step 9. (This rule follows [OData-URL, section 4.11](#ODataURL) rather than [OData-CSDL, section 14.4.1.1](#ODataCSDL).)
+5. Otherwise, $p_1$ is a non-type-cast segment. If $u$ does not contain a structural or navigation property $p_1$, let $B$ be an empty collection and continue with step 9.
+6. If $p_1$ is single-valued, let $v$ be the value of the structural or navigation property $p_1$ in $u$. If $v$ is null, let $B$ be an empty collection and continue with step 9; otherwise continue with step 8.
+7. Otherwise, $p_1$ is collection-valued. Let $C$ be the collection addressed by the structural or navigation property $p_1$ in $u$, and let $B=\Gamma(C,p_2)$. Then continue with step 9.
+8. Let $B=γ(v,p_2)$.
9. Return $B$.
-This notation is extended to the case of an empty path $e$ by setting $\Gamma(A,e)=A$. Note every $u$ in $\Gamma(A,v)$ occurs also in $A$ or nested into $A$, therefore an algorithmic step like "Add a dynamic property to each $u$ in $\Gamma(A,v)$" effectively changes $A$.
+This notation is extended to the case of an empty path $e$ by setting $\Gamma(A,e)=A$. Note every $u$ in $\Gamma(A,p)$ occurs also in $A$ or nested into $A$, therefore an algorithmic step like "Add a dynamic property to each $u$ in $\Gamma(A,p)$" effectively changes $A$.
diff --git a/odata-data-aggregation-ext/3.2 Basic Aggregation.md b/odata-data-aggregation-ext/3.2 Basic Aggregation.md
index 97f56896c..60ccb935c 100644
--- a/odata-data-aggregation-ext/3.2 Basic Aggregation.md
+++ b/odata-data-aggregation-ext/3.2 Basic Aggregation.md
@@ -6,29 +6,29 @@
The `aggregate` transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance of the [input type](#TypeStructureandContextURL) without entity-id containing one property per aggregate expression, representing the aggregated value of the input set.
-An aggregate expression MUST have one of the types listed below. To compute the value of the property for a given aggregate expression, the `aggregate` transformation first determines a collection $U$ of instances or primitive values, based on the input set of the `aggregate` transformation, and a path $p$ that occurs in the aggregate expression. Let $p_1$ denote a [data aggregation path](#DataAggregationPath) with single- or collection-valued segments and $p_2$ a type-cast segment. Depending on the type of aggregate expression, $p=p_1$ or $p=p_2$ or $p=p_1/p_2$. Each type of aggregate expression defines a function $f(U)$ which the aggregate transformation evaluates to obtain the property value.
+An aggregate expression MUST have one of the types listed below. To compute the value of the property for a given aggregate expression, the `aggregate` transformation first determines a collection $A$ of instances or primitive values, based on the input set of the `aggregate` transformation, and a path $p$ that occurs in the aggregate expression. Let $p_1$ denote a [data aggregation path](#DataAggregationPath) with single- or collection-valued segments and $p_2$ a type-cast segment. Depending on the type of aggregate expression, $p=p_1$ or $p=p_2$ or $p=p_1/p_2$. Each type of aggregate expression defines a function $f(A)$ which the aggregate transformation evaluates to obtain the property value.
The property is a dynamic property, except for a special case in type 4. In types 1 and 2, the aggregate expression MUST end with the keyword `with` and an aggregation method $g$. The aggregation method also determines the type of the dynamic property. In types 1, 2 and 3 the aggregate expression MUST, and in type 4 it MAY, be followed by the keyword [`as`](#Keywordas) and an [alias](#TypeStructureandContextURL), which is then the name of the dynamic property. More aggregate expressions can be constructed with the [`from`](#Keywordfrom) keyword, see later section.
_Types of aggregate expressions:_
1. A path $p=p_1$ or $p=p_1/p_2$ where the last segment of $p_1$ has a complex or entity or [aggregatable primitive type](#AggregatablePrimitiveType) whose values can be aggregated using the specified [aggregation method](#AggregationMethods) $g$, or $p=p_2$ if the input set can be aggregated using the [custom aggregation method](#CustomAggregationMethods) $g$.
-Let $f(U)=g(U)$.
+Let $f(A)=g(A)$.
2. An [aggregatable expression](#AggregatableExpression).
-Let $f(U)=g(V)$ where $V$ is the collection consisting of the aggregatable expression evaluated relative to each member of $U$ with null values removed from $V$. In this type, $p$ is absent.
+Let $f(A)=g(B)$ where $B$ is the collection consisting of the aggregatable expression evaluated relative to each member of $A$ with null values removed from $B$. In this type, $p$ is absent.
3. A path $p/{\tt\$count}$ (see [section ##AggregateExpressioncount]) with optional prefix $p/{}$ where $p=p_1$ or $p=p_2$ or $p=p_1/p_2$.
-Let $f(U)$ be the [cardinality](#SamenessandPrecedence) of $U$.
+Let $f(A)$ be the [cardinality](#SamenessandPrecedence) of $A$.
4. A path $p/c$ consisting of an optional prefix $p/{}$ with $p=p_1$ or $p=p_1/p_2$ where the last segment of $p_1$ has a structured type or $p=p_2$, and a [custom aggregate](#CustomAggregates) $c$ defined on the collection addressed by $p$.
-Let $f(U)=c(U)$, if computation of the custom aggregate fails, the service MUST reject the request. In the absence of an alias, the name of the property MUST be the name of the custom aggregate, this is a dynamic property unless there is a declared property with that name, which is allowed by the `CustomAggregate` annotation. The custom aggregate also determines the type of the dynamic property.
+Let $f(A)=c(A)$, if computation of the custom aggregate fails, the service MUST reject the request. In the absence of an alias, the name of the property MUST be the name of the custom aggregate, this is a dynamic property unless there is a declared property with that name, which is allowed by the `CustomAggregate` annotation. The custom aggregate also determines the type of the dynamic property.
-_Determination of $U$:_
+_Determination of $A$:_
-Let $I$ be the input set. If $p$ is absent, let $U=I$ with null values removed.
+Let $I$ be the input set. If $p$ is absent, let $A=I$ with null values removed.
Otherwise, let $q$ be the portion of $p$ up to and including the last navigation property, if any, and any type-cast segment that immediately follows, and let $r$ be the remainder, if any, of $p$ that contains no navigation properties, such that $p$ equals the concatenated path $q⁄r$. The aggregate transformation considers each entity reached via the path $q$ exactly once. To this end, using the [$\Gamma$ notation](#EvaluationofDataAggregationPaths):
- If $q$ is non-empty, let $E=\Gamma(I,q)$ and remove duplicates from that entity collection: If [multiple representations of the same non-transient entity](#SamenessandPrecedence) are reached, the service MUST merge them into one occurrence in $E$ if they are complementary and MUST reject the request if they are contradictory. (See [example ##aggrconflict].) If [multiple occurrences of the same transient entity](#SamenessandPrecedence) are reached, the service MUST keep only one occurrence in $E$.
- If $q$ is empty, let $E=I$.
-Then, if $r$ is empty, let $U=E$, otherwise let $U=\Gamma(E,r)$, this consists of instances or primitive values, possibly with repetitions.
+Then, if $r$ is empty, let $A=E$, otherwise let $A=\Gamma(E,r)$, this consists of instances or primitive values, possibly with repetitions.
#### ##subsubsubsec Keyword `as`
@@ -329,12 +329,12 @@ The algorithmic description of this transformation makes use of the following de
The output set of the groupby transformation is constructed in five steps.
1. [For each](#SamenessandPrecedence) instance $u$ in the input set, a projection is computed that contains only the grouping properties. This projection is $s_G(u,e)$ and the function $s_G(u,p)$ takes an instance and a path relative to the input set as arguments and is computed recursively as follows:
- - Let $w$ be an instance of the type of $u$ without properties and without entity-id.
+ - Let $v$ be an instance of the type of $u$ without properties and without entity-id.
- For each structural or navigation property $q$ of $u$:
- If $u$ has a subtype of the type addressed by $p$ and $q$ is only declared on that subtype, let $p'=p/p''/q$ where $p''$ is a type-cast to the subtype, otherwise let $p'=p/q$.
- - If $p'$ occurs in $G$, let $w[q]=u[q]$.
- - Otherwise, if $p'$ is a prefix of a path in $G$, let $w[q]=s_G(u[q],p')$.
- - Return $w$.
+ - If $p'$ occurs in $G$, let $v[q]=u[q]$.
+ - Otherwise, if $p'$ is a prefix of a path in $G$, let $v[q]=s_G(u[q],p')$.
+ - Return $v$.
2. The input set is split into subsets where two instances are in the same subset if their projections are [the same](#SamenessandPrecedence). If [representations of the same non-transient entity](#SamenessandPrecedence) are encountered during the comparison of two projections, the service MUST assign them to one subset with the merged representation if they are complementary and MUST reject the request if they are contradictory.
3. The set transformations from the second parameter are applied to each subset, resulting in a new set of potentially different structure and cardinality. Associated with each resulting set is the common projection of the instances in the subset from which the resulting set was computed.
4. Each set resulting from the previous step is transformed to contain the associated common projection $s$. This transformation is denoted by $\Pi_G(s)$ and is defined below.
diff --git a/odata-data-aggregation-ext/3.4 Transformations Changing the Input Set Structure.md b/odata-data-aggregation-ext/3.4 Transformations Changing the Input Set Structure.md
index 9b0db53c0..58debcadd 100644
--- a/odata-data-aggregation-ext/3.4 Transformations Changing the Input Set Structure.md
+++ b/odata-data-aggregation-ext/3.4 Transformations Changing the Input Set Structure.md
@@ -40,14 +40,14 @@ results in
The `join` and `outerjoin` transformations take as their first parameter $p$ a collection-valued complex property or navigation property, optionally followed by a type-cast segment to address only instances of that derived type or one of its sub-types, followed by the `as` keyword, followed by an [alias](#TypeStructureandContextURL). The optional second parameter specifies a transformation sequence $T$.
[For each](#SamenessandPrecedence) instance $u$ in an [order-preserving loop](#SamenessandPrecedence) over the input set
-1. the instance collection $U$ addressed by $p$ is identified.
-2. If $T$ is provided, $U$ is replaced with the result of applying $T$ to $U$.
-3. In case of an `outerjoin`, if $U$ is empty, a null instance is added to it.
-4. [For each](#SamenessandPrecedence) instance $w$ in an [order-preserving loop](#SamenessandPrecedence) over $U$
- - an instance $x$ is appended to the output set of the transformation.
- - The instance $x$ is a clone of $u$ with an additional dynamic property whose name is the given alias and whose value is $w$.
- - The property $x$ is a navigation property if $p$ is a collection-valued navigation property, otherwise it is a complex property.
- - The property $x$ carries as control information the context URL of $u$.
+1. the instance collection $A$ addressed by $p$ is identified.
+2. If $T$ is provided, $A$ is replaced with the result of applying $T$ to $A$.
+3. In case of an `outerjoin`, if $A$ is empty, a null instance is added to it.
+4. [For each](#SamenessandPrecedence) instance $v$ in an [order-preserving loop](#SamenessandPrecedence) over $A$
+ - an instance $w$ is appended to the output set of the transformation.
+ - The instance $w$ is a clone of $u$ with an additional dynamic property whose name is the given alias and whose value is $v$.
+ - The property $w$ is a navigation property if $p$ is a collection-valued navigation property, otherwise it is a complex property.
+ - The property $w$ carries as control information the context URL of $u$.
::: example
Example ##ex: all links between products and sales instances
@@ -135,12 +135,12 @@ Further parameters are one or more transformation sequences followed by the as k
If $p_k$ is single-valued, the transformation sequences MUST consist of only `identity` or `compute` or `addnested` transformations, because these transform one-element collections into one-element collections. This makes it meaningful to speak (in this section only) of a transformation sequence applied to a single instance; this means applying it to a collection containing the single instance and taking as result the single instance from the output set.
-[For each](#SamenessandPrecedence) instance $u$ in $\Gamma(A,p_1/…/p_{k-1})$, let $U=γ(u,p_k/q)$ and let the resource $w$ be
-- the collection $U$ if $p_k$ is collection-valued
-- the single instance in $U$ if $p_k$ is single-valued and $U$ is non-empty
-- undefined if $p_k$ is single-valued and $U$ is empty.
+[For each](#SamenessandPrecedence) instance $u$ in $\Gamma(A,p_1/…/p_{k-1})$, let $B=γ(u,p_k/q)$ and let the resource $v$ be
+- the collection $B$ if $p_k$ is collection-valued
+- the single instance in $B$ if $p_k$ is single-valued and $B$ is non-empty
+- undefined if $p_k$ is single-valued and $B$ is empty.
-If $w$ is defined, then for each transformation sequence, a dynamic property is added to $u$ as follows: If $p_k$ is a navigation property, the added property is a dynamic navigation property, which is expanded by default, otherwise it is a dynamic structural property. Its name is the alias of the transformation sequence. The value of the added property is the result of the transformation sequence applied to $w$. The dynamic property carries as control information the context URL of $w$.
+If $v$ is defined, then for each transformation sequence, a dynamic property is added to $u$ as follows: If $p_k$ is a navigation property, the added property is a dynamic navigation property, which is expanded by default, otherwise it is a dynamic structural property. Its name is the alias of the transformation sequence. The value of the added property is the result of the transformation sequence applied to $v$. The dynamic property carries as control information the context URL of $v$.
::: example
Example ##ex:
diff --git a/odata-data-aggregation-ext/6 Hierarchical Transformations.md b/odata-data-aggregation-ext/6 Hierarchical Transformations.md
index dd25fd4f0..3d799ab80 100644
--- a/odata-data-aggregation-ext/6 Hierarchical Transformations.md
+++ b/odata-data-aggregation-ext/6 Hierarchical Transformations.md
@@ -18,7 +18,7 @@ The parameter lists defined in the following subsections have three mandatory pa
The recursive hierarchy is defined by a parameter pair $(H,Q)$, where $H$ and $Q$ MUST be specified as the first and second parameter. Here, $H$ MUST be an expression of type `Collection(Edm.EntityType)` starting with `$root` that has no multiple occurrences of the same entity. $H$ identifies the collection of node entities forming a recursive hierarchy based on an annotation of their common entity type with term `RecursiveHierarchy` with a `Qualifier` attribute whose value MUST be provided in $Q$. The property paths referenced by `NodeProperty` and `ParentNavigationProperty` in the `RecursiveHierarchy` annotation must be evaluable for the nodes in the recursive hierarchy, otherwise the service MUST reject the request. The `NodeProperty` is denoted by $q$ in this section.
-The third parameter MUST be a data aggregation path $p$ with single- or collection-valued segments whose last segment MUST be a primitive property. The node identifier(s) of an instance $u$ in the input set are the primitive values in $γ(u,p)$ reached via $p$ starting from $u$. Let $p=p_1/…/p_k/s$ with $k≥0$ be the concatenation where each sub-path $p_1,…,p_k$ consists of a collection-valued segment that is optionally followed by a type-cast segment and preceded by zero or more single-valued segments, and either $s$ consists of one or more single-valued segments or $k≥1$ and ${}/s$ is absent.
+The third parameter MUST be a data aggregation path $p$ with single- or collection-valued segments whose last segment MUST be a primitive property. The node identifier(s) of an instance $u$ in the input set are the primitive values in $γ(u,p)$ reached via $p$ starting from $u$. Let $p=p_1/…/p_k/r$ with $k≥0$ be the concatenation where each sub-path $p_1,…,p_k$ consists of a collection-valued segment that is optionally followed by a type-cast segment and preceded by zero or more single-valued segments, and either $r$ consists of one or more single-valued segments or $k≥1$ and ${}/r$ is absent.
The recursive hierarchy to be processed can also be a subset $H'$ of $H$. For this case a non-empty sequence $S$ of transformations MAY be specified as an optional parameter whose position varies from transformation to transformation and is given below. In general, let $H'$ be the output set of the transformation sequence $S$ applied to $H$, or $H'=H$ if $S$ is not specified. The transformations in $S$ MUST be listed in the section on [Transformations Preserving the Input Set Structure](#TransformationsPreservingtheInputSetStructure) or in the section on [Hierarchical Transformations Preserving the Input Set Structure](#HierarchicalTransformationsPreservingtheInputSetStructure) or be service-defined bound functions whose output set is a subset of the input set.
@@ -57,7 +57,7 @@ F(u)={\tt filter}(\hbox{\tt Aggregation.isdescendant}(\hfill\\
\quad {\tt Node}=p,\;{\tt Ancestor}=u[p],\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true})).\hfill
}$$
-Otherwise $p=p_1/…/p_k/s$ with $k≥1$, in this case the output set of the transformation $F(u)$ is defined as the [union](#HierarchicalTransformations) of the output sets of transformations $G(n)$ applied to the input set for all $n$ in $γ(u,p)$. The output set of $G(n)$ consists of the instances of the input set whose node identifier is an ancestor or descendant of the node identifier $n$:
+Otherwise $p=p_1/…/p_k/r$ with $k≥1$, in this case the output set of the transformation $F(u)$ is defined as the [union](#HierarchicalTransformations) of the output sets of transformations $G(n)$ applied to the input set for all $n$ in $γ(u,p)$. The output set of $G(n)$ consists of the instances of the input set whose node identifier is an ancestor or descendant of the node identifier $n$:
For `ancestors`,
$$\matrix{
@@ -68,7 +68,7 @@ G(n)={\tt filter}(\hfill\\
\hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\
\hskip5pc \hbox{\tt Aggregation.isancestor}(\hfill\\
\hskip6pc {\tt HierarchyNodes}=H',\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\
-\hskip6pc {\tt Node}=y_k/s,\;{\tt Descendant}=n,\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}\hfill\\
+\hskip6pc {\tt Node}=y_k/r,\;{\tt Descendant}=n,\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}\hfill\\
\hskip5pc )\hfill\\
\hskip4pc )\hfill\\
\hskip3pc ⋰\hfill\\
@@ -85,7 +85,7 @@ G(n)={\tt filter}(\hfill\\
\hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\
\hskip5pc \hbox{\tt Aggregation.isdescendant}(\hfill\\
\hskip6pc {\tt HierarchyNodes}=H',\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\
-\hskip6pc {\tt Node}=y_k/s,\;{\tt Ancestor}=n,\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}\hfill\\
+\hskip6pc {\tt Node}=y_k/r,\;{\tt Ancestor}=n,\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}\hfill\\
\hskip5pc )\hfill\\
\hskip4pc )\hfill\\
\hskip3pc ⋰\hfill\\
@@ -93,7 +93,7 @@ G(n)={\tt filter}(\hfill\\
\hskip1pc )\hfill\\
)\hfill
}$$
-where $y_1,…,y_k$ denote `lambdaVariableExpr`s and ${}/s$ may be absent.
+where $y_1,…,y_k$ denote `lambdaVariableExpr`s and ${}/r$ may be absent.
If parameter $d$ is absent, the parameter ${\tt MaxDistance}=d$ is omitted. If `keep start` is absent, the parameter ${\tt IncludeSelf}={\tt true}$ is omitted.
@@ -233,21 +233,21 @@ $F(x)$ is a transformation that determines for the specified node $x$ the instan
If $p$ contains only single-valued segments, then
$$F(x)={\tt filter}(p{\tt\ eq\ }x[q]).$$
-Otherwise $p=p_1/…/p_k/s$ with $k≥1$ and
+Otherwise $p=p_1/…/p_k/r$ with $k≥1$ and
$$\matrix{
F(x)={\tt filter}(\hfill\\
\hskip1pc p_1/{\tt any}(y_1:\hfill\\
\hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\
\hskip3pc ⋱\hfill\\
\hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\
-\hskip5pc y_k/s{\tt\ eq\ }x[q]\hfill\\
+\hskip5pc y_k/r{\tt\ eq\ }x[q]\hfill\\
\hskip4pc )\hfill\\
\hskip3pc ⋰\hfill\\
\hskip2pc )\hfill\\
\hskip1pc )\hfill\\
)\hfill
}$$
-where $y_1,…,y_k$ denote `lambdaVariableExpr`s and ${}/s$ may be absent.
+where $y_1,…,y_k$ denote `lambdaVariableExpr`s and ${}/r$ may be absent.
::: example
Example ##ex: Based on the `SalesOrgHierarchy` defined in [Hierarchy Examples](#HierarchyExamples)
@@ -340,7 +340,7 @@ F(x)={\tt filter}(\hbox{\tt Aggregation.isdescendant}(\hfill\\
\quad {\tt Node}=p,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true})).\hfill
}$$
-Otherwise $p=p_1/…/p_k/s$ with $k≥1$ and
+Otherwise $p=p_1/…/p_k/r$ with $k≥1$ and
$$\matrix{
F(x)={\tt filter}(\hfill\\
\hskip1pc p_1/{\tt any}(y_1:\hfill\\
@@ -349,7 +349,7 @@ F(x)={\tt filter}(\hfill\\
\hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\
\hskip5pc \hbox{\tt Aggregation.isdescendant}(\hfill\\
\hskip6pc {\tt HierarchyNodes}=H',\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\
-\hskip6pc {\tt Node}=y_k/s,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true}\hfill\\
+\hskip6pc {\tt Node}=y_k/r,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true}\hfill\\
\hskip5pc )\hfill\\
\hskip4pc )\hfill\\
\hskip3pc ⋰\hfill\\
@@ -357,7 +357,7 @@ F(x)={\tt filter}(\hfill\\
\hskip1pc )\hfill\\
)\hfill
}$$
-where $y_1,…,y_k$ denote `lambdaVariableExpr`s and ${}/s$ may be absent. (See [example ##rollupcoll] for a case with $k=1$.)
+where $y_1,…,y_k$ denote `lambdaVariableExpr`s and ${}/r$ may be absent. (See [example ##rollupcoll] for a case with $k=1$.)
Non-normatively speaking, the effect of the algorithm can be summarized as follows: If $M≥1$ and $\hat F_N(x)$ denotes the collection of all instances that are related to a node $x$ from the recursive hierarchy of the $N$-th `rolluprecursive` operator, then $T$ is applied to each of the intersections of $\hat F_1(χ_1),…,\hat F_M(χ_M)$, as $χ_N$ runs over all nodes of the $N$-th recursive hierarchy for $1≤N≤M$. Into the instances of the resulting output sets the $\Pi_G$ transformations inject information about the nodes $χ_1,…,χ_M$.
diff --git a/odata-data-aggregation-ext/7 Examples.md b/odata-data-aggregation-ext/7 Examples.md
index 854abfd83..5aa53ad39 100644
--- a/odata-data-aggregation-ext/7 Examples.md
+++ b/odata-data-aggregation-ext/7 Examples.md
@@ -186,7 +186,7 @@ results in
}
```
-Note that the base set of the request is `Products`, so there is a result item for product `Pencil` even though there are no sales items. The input set for the aggregation in the third row is $I$ consisting of the pencil, $p=q/r={\tt Sales}/{\tt Amount}$, $E=\Gamma(I,q)$ is empty and $U=\Gamma(E,r)$ is also empty. The sum over the empty collection is null.
+Note that the base set of the request is `Products`, so there is a result item for product `Pencil` even though there are no sales items. The input set for the aggregation in the third row is $I$ consisting of the pencil, $p=q/r={\tt Sales}/{\tt Amount}$, $E=\Gamma(I,q)$ is empty and $A=\Gamma(E,r)$ is also empty. The sum over the empty collection is null.
:::
::: example
@@ -1208,7 +1208,7 @@ results in
:::
::: example
-Example ##ex_traversecoll: Preorder traversal of a hierarchy with 1:N relationship with collection-valued segment $p_1={\tt Sales}$ and $s={\tt SalesOrganization}/{\tt ID}$.
+Example ##ex_traversecoll: Preorder traversal of a hierarchy with 1:N relationship with collection-valued segment $p_1={\tt Sales}$ and $r={\tt SalesOrganization}/{\tt ID}$.
```
GET /service/Products?$apply=traverse(
$root/SalesOrganizations,
From 884e089fabd64956b5504f9abaa726ea68ace732 Mon Sep 17 00:00:00 2001
From: D024504
Date: Thu, 25 May 2023 15:59:57 +0200
Subject: [PATCH 010/116] CSDL-XML-Link
---
.../odata-data-aggregation-ext.html | 9 ++++++++-
.../odata-data-aggregation-ext.md | 5 ++++-
odata-data-aggregation-ext/8 Conformance.md | 5 ++++-
3 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
index a6679ba02..cbfc89ce7 100644
--- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
+++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
@@ -6512,7 +6512,14 @@ [OData-CSDL]
https://docs.oasis-open.org/odata/odata-csdl-json/v4.01/os/odata-csdl-json-v4.01-os.html.
Latest stage: https://docs.oasis-open.org/odata/odata-csdl-json/v4.01/odata-csdl-json-v4.01.html.
+href="https://docs.oasis-open.org/odata/odata-csdl-json/v4.01/odata-csdl-json-v4.01.html">https://docs.oasis-open.org/odata/odata-csdl-json/v4.01/odata-csdl-json-v4.01.html
.
+OData Common Schema Definition Language (CSDL) XML Representation
+Version 4.01. Edited by Michael Pizzo, Ralf Handl, and Martin Zurmuehl.
+11 May 2020. OASIS Standard.
+https://docs.oasis-open.org/odata/odata-csdl-xml/v4.01/os/odata-csdl-xml-v4.01-os.html.
+Latest stage: https://docs.oasis-open.org/odata/odata-csdl-xml/v4.01/odata-csdl-xml-v4.01.html.
[OData-JSON]
OData JSON Format Version 4.01. Edited by Michael Pizzo, Ralf
Handl, and Mark Biamonte. 11 May 2020. OASIS Standard.
diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
index 6f6b94e84..ed18aac41 100644
--- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
+++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
@@ -4520,7 +4520,10 @@ See link in "[Additional artifacts](#AdditionalArtifacts)" section on cover page
###### [OData-CSDL]
_OData Common Schema Definition Language (CSDL) JSON Representation Version 4.01. Edited by Michael Pizzo, Ralf Handl, and Martin Zurmuehl. 11 May 2020. OASIS Standard._
https://docs.oasis-open.org/odata/odata-csdl-json/v4.01/os/odata-csdl-json-v4.01-os.html.
-Latest stage: https://docs.oasis-open.org/odata/odata-csdl-json/v4.01/odata-csdl-json-v4.01.html.
+Latest stage: https://docs.oasis-open.org/odata/odata-csdl-json/v4.01/odata-csdl-json-v4.01.html.
+_OData Common Schema Definition Language (CSDL) XML Representation Version 4.01. Edited by Michael Pizzo, Ralf Handl, and Martin Zurmuehl. 11 May 2020. OASIS Standard._
+https://docs.oasis-open.org/odata/odata-csdl-xml/v4.01/os/odata-csdl-xml-v4.01-os.html.
+Latest stage: https://docs.oasis-open.org/odata/odata-csdl-xml/v4.01/odata-csdl-xml-v4.01.html.
###### [OData-JSON]
_OData JSON Format Version 4.01. Edited by Michael Pizzo, Ralf Handl, and Mark Biamonte. 11 May 2020. OASIS Standard._
diff --git a/odata-data-aggregation-ext/8 Conformance.md b/odata-data-aggregation-ext/8 Conformance.md
index 5082a94bf..8fae32566 100644
--- a/odata-data-aggregation-ext/8 Conformance.md
+++ b/odata-data-aggregation-ext/8 Conformance.md
@@ -29,7 +29,10 @@ See link in "[Additional artifacts](#AdditionalArtifacts)" section on cover page
###### [OData-CSDL]
_OData Common Schema Definition Language (CSDL) JSON Representation Version 4.01. Edited by Michael Pizzo, Ralf Handl, and Martin Zurmuehl. 11 May 2020. OASIS Standard._
https://docs.oasis-open.org/odata/odata-csdl-json/v4.01/os/odata-csdl-json-v4.01-os.html.
-Latest stage: https://docs.oasis-open.org/odata/odata-csdl-json/v4.01/odata-csdl-json-v4.01.html.
+Latest stage: https://docs.oasis-open.org/odata/odata-csdl-json/v4.01/odata-csdl-json-v4.01.html.
+_OData Common Schema Definition Language (CSDL) XML Representation Version 4.01. Edited by Michael Pizzo, Ralf Handl, and Martin Zurmuehl. 11 May 2020. OASIS Standard._
+https://docs.oasis-open.org/odata/odata-csdl-xml/v4.01/os/odata-csdl-xml-v4.01-os.html.
+Latest stage: https://docs.oasis-open.org/odata/odata-csdl-xml/v4.01/odata-csdl-xml-v4.01.html.
###### [OData-JSON]
_OData JSON Format Version 4.01. Edited by Michael Pizzo, Ralf Handl, and Mark Biamonte. 11 May 2020. OASIS Standard._
From 3ec305985e35dc9ae2d0baad22dc80e58c0b926e Mon Sep 17 00:00:00 2001
From: D024504
Date: Thu, 25 May 2023 16:57:46 +0200
Subject: [PATCH 011/116] Non-standard roots
---
.../odata-data-aggregation-ext.html | 110 +++++++++++-------
.../odata-data-aggregation-ext.md | 33 +++---
.../5 Vocabulary for Data Aggregation.md | 15 ++-
.../6 Hierarchical Transformations.md | 18 +--
4 files changed, 105 insertions(+), 71 deletions(-)
diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
index 6725975e3..edad64057 100644
--- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
+++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
@@ -4013,12 +4013,21 @@ 5.5
segments ending in a primitive property. This path points to the
property holding the node identifier of the node in the hierarchy.
Entities for which this path evaluates to null are not nodes of the
-hierarchy (sometimes called "orphans").
+hierarchy.
The ParentNavigationProperty
allows navigation to the
instance or instances representing the parent nodes. It MUST be a
collection-valued or nullable single-valued navigation property path
that addresses the entity type annotated with this term. Nodes MUST NOT
form cycles when following parent navigation properties.
+IsRoot
is a Boolean value and nodes in the hierarchy
+for which this is true are called root nodes. A recursive
+hierarchy can have one or more root nodes. The standard definition
+for root is "node without parents", which for a single-valued
+ParentNavigationProperty
is expressed by giving the
+IsRoot
property a dynamic annotation value OData-CSDL, section 14.4 like in example 51. The standard definition for root is
+also implied if the IsRoot
property is null or absent.
The term RecursiveHierarchy
can only be applied to
entity types, and MUST be applied with a qualifier, which is used to
@@ -4028,19 +4037,18 @@
5.5
href="#HierarchyFunctions">hierarchy functions. The same entity can
serve as different nodes in different recursive hierarchies, given
different qualifiers.
-A node without parent node is a root node, a node is a
-child node of its parent nodes, a node without child nodes is a
-leaf node. Two nodes with a common parent node are sibling
-nodes and so are two root nodes. The descendants of a node
-are its child nodes, their child nodes, and so on, up to and including
-all leaf nodes that can be reached. A node together with its descendants
-forms a sub-hierarchy of the hierarchy. The ancestors
-of a node are its parent nodes, the parents of its parent nodes, and so
-on, up to and including root nodes that can be reached. A recursive
-hierarchy can have one or more root nodes.
+A node is a child node of its parent nodes, a node without
+child nodes is a leaf node. Two nodes with a common parent node
+are sibling nodes and so are two root nodes. The
+descendants of a node are its child nodes, their child nodes,
+and so on, up to and including all leaf nodes that can be reached. A
+node together with its descendants forms a sub-hierarchy of the
+hierarchy. The ancestors of a node are its parent nodes, the
+parents of its parent nodes, and so on, until no more parent nodes
+exist.
The term UpNode
can be used in hierarchical result sets
to associate with each instance one of its ancestors, which is again
-annotated with UpNode
and so on until a path to the root is
+annotated with UpNode
and so on until a path to a root is
constructed.
5.5.2.1
@@ -4086,8 +4094,9 @@ 5.5
Hierarchy Examples
The hierarchy terms can be applied to the Example Data Model.
-Example 51: leveled hierarchies for products and time, and a
-recursive hierarchy for the sales organizations
+Example 51: leveled
+hierarchies for products and time, and a recursive hierarchy for the
+sales organizations
edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"
< Version="4.0">
@@ -4127,12 +4136,18 @@ 5.5
PropertyPath="ID" />
PropertyValue Property="ParentNavigationProperty"
< PropertyPath="Superordinate" />
-Record>
- </Annotation>
- </Annotations>
- </Schema>
- </edmx:DataServices>
- </edmx:Edmx> </
+PropertyValue Property="IsRoot">
+ <Eq>
+ <Path>Superordinate</Path>
+ <Null />
+ <Eq>
+ </PropertyValue>
+ </Record>
+ </Annotation>
+ </Annotations>
+ </Schema>
+ </edmx:DataServices>
+ </edmx:Edmx> </
The recursive hierarchy SalesOrgHierarchy
can be used in
functions with the $filter
system query option.
@@ -4677,8 +4692,8 @@ 5.5
(See Example 107.)
Let \(r_1,…,r_n\) be a sequence of
-the root nodes of the recursive hierarchy \((H',Q)\) root nodes of the recursive
+hierarchy \((H',Q)\) preserving the order of \(H'\) stable-sorted by \(o\). Then the transformation 5.5
class="math inline">\(x\). Let \(c_1,…,c_m\) with \(m≥0\) be an order-preserving sequence of the
-children of \(x\) in order-preserving sequence
of the children of \(x\) in \((H',Q)\). The recursive formula for
\(R(x)\) is as follows:
If \(h={\tt preorder}\), then 5.5
}
The algorithm given so far is valid for a single-valued
-RecursiveHierarchy/ParentNavigationProperty
. The remainder
-of this section describes the case where it is collection-valued.
If the recursive algorithm reaches a node RecursiveHierarchy/ParentNavigationProperty with the standard definition for root. The +remainder of this section describes the general case.
+In the general case, the recursive algorithm can reach a node \(x\) multiple times, via different parents -or ancestors, then the output set contains multiple instances that -include \(σ(x)\). In order to -distinguish these, information about the ancestors up to the root is -injected into each \(σ(x)\) by +or ancestors, or because \(x\) is a +root and a child at the same time. Then the output set contains multiple +instances that include \(σ(x)\). In +order to distinguish these, information about the ancestors up to the +root is injected into each \(σ(x)\) by annotating \(x\) differently before each \(σ(x)\) is computed.
-More precisely, a path-to-the-root is a node More precisely, an path-to-the-root is a node \(x\) that is annotated with the term
If \(h={\tt postorder}\), then \[R(x)={\tt
concat}(R(ρ(c_1,x)),…,R(ρ(c_m,x)),F(x)/\Pi_G(σ(x))).\] If there is only one parent, the result is the same as in the
-single-parent case, except for the presence of the
- If there is only one parent and the standard definition for root is
+in force, the result is the same as in the single-parent case, except
+for the presence of the UpNode
from the Aggregation
vocabulary OData-VocAggr where the annotation value is the
@@ -4794,9 +4812,9 @@ 5.5
is a transformation whose output set
is its input set with property \(χ_N\)
removed.Aggregation.UpNode
annotations.Aggregation.UpNode
annotations.6.3
Grouping with
@@ -4846,10 +4864,10 @@ rolluprecursive
5.5
class="math inline">\(Z_N\)
If \(r_1,…,r_n\) are the root nodes
-of the recursive hierarchy \((H',Q)\), the transformation \({\tt groupby}((P_1,{\tt
+ If \(r_1,…,r_n\) are the root nodes of the recursive hierarchy
+\((H',Q)\), the transformation
+\({\tt groupby}((P_1,{\tt
rolluprecursive}(H,Q,p,S),P_2),T)\) is defined as equivalent to
\[{\tt concat}(R(r_1),…,R(r_n))\] with
no order defined on the output set.5.5
class="math inline">\(x\)
(see (1) below) and then recurs for all
children of \(x\) (see (2) below). Its
output set is a collection of aggregated instances for all rollup
-results. Let \(c_1,…,c_m\) be the
-children of \(x\) in \(c_1,…,c_m\) be the children of \(x\) in \((H',Q)\):
If at least one of \(P_1\) or \(P_2\) is non-empty, then 5.5
}
The algorithm given so far is valid for a single-valued
- With \(r_1,…,r_n\) as above, \({\tt groupby}((P_1,{\tt
diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
index c56617e05..8c262c53f 100644
--- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
+++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
@@ -2412,14 +2412,15 @@ A recursive hierarchy is defined on a collection of entities by associating with
A recursive hierarchy does not need to be as uniform as a leveled hierarchy.
The recursive hierarchy is described in the model by an annotation of the entity type with the complex term `RecursiveHierarchy` with these properties:
-- The `NodeProperty` contains a path with single-valued segments ending in a primitive property. This path points to the property holding the node identifier of the node in the hierarchy. Entities for which this path evaluates to null are not nodes of the hierarchy (sometimes called "orphans").
+- The `NodeProperty` contains a path with single-valued segments ending in a primitive property. This path points to the property holding the node identifier of the node in the hierarchy. Entities for which this path evaluates to null are not nodes of the hierarchy.
- The `ParentNavigationProperty` allows navigation to the instance or instances representing the parent nodes. It MUST be a collection-valued or nullable single-valued navigation property path that addresses the entity type annotated with this term. Nodes MUST NOT form cycles when following parent navigation properties.
+- `IsRoot` is a Boolean value and nodes in the hierarchy for which this is true are called _root nodes_. A recursive hierarchy can have one or more root nodes. The _standard definition for root_ is "node without parents", which for a single-valued `ParentNavigationProperty` is expressed by giving the `IsRoot` property a dynamic annotation value [OData-CSDL, section 14.4](#ODataCSDL) like in [example 51](#salesorghier). The standard definition for root is also implied if the `IsRoot` property is null or absent.
The term `RecursiveHierarchy` can only be applied to entity types, and MUST be applied with a qualifier, which is used to reference the hierarchy in transformations operating on recursive hierarchies, in [grouping with `rolluprecursive`](#Groupingwithrolluprecursive), and in [hierarchy functions](#HierarchyFunctions). The same entity can serve as different nodes in different recursive hierarchies, given different qualifiers.
-A node without parent node is a _root node_, a node is a _child node_ of its parent nodes, a node without child nodes is a _leaf node_. Two nodes with a common parent node are _sibling nodes_ and so are two root nodes. The _descendants_ of a node are its child nodes, their child nodes, and so on, up to and including all leaf nodes that can be reached. A node together with its descendants forms a _sub-hierarchy_ of the hierarchy. The _ancestors_ of a node are its parent nodes, the parents of its parent nodes, and so on, up to and including root nodes that can be reached. A recursive hierarchy can have one or more root nodes.
+A node is a _child node_ of its parent nodes, a node without child nodes is a _leaf node_. Two nodes with a common parent node are _sibling nodes_ and so are two root nodes. The _descendants_ of a node are its child nodes, their child nodes, and so on, up to and including all leaf nodes that can be reached. A node together with its descendants forms a _sub-hierarchy_ of the hierarchy. The _ancestors_ of a node are its parent nodes, the parents of its parent nodes, and so on, until no more parent nodes exist.
-The term `UpNode` can be used in hierarchical result sets to associate with each instance one of its ancestors, which is again annotated with `UpNode` and so on until a path to the root is constructed.
+The term `UpNode` can be used in hierarchical result sets to associate with each instance one of its ancestors, which is again annotated with `UpNode` and so on until a path to a root is constructed.
#### 5.5.2.1 Hierarchy Functions
@@ -2441,7 +2442,7 @@ The following functions are defined:
The hierarchy terms can be applied to the Example Data Model.
::: example
-Example 51: leveled hierarchies for products and time, and a recursive hierarchy for the sales organizations
+Example 51: leveled hierarchies for products and time, and a recursive hierarchy for the sales organizations
```xml
The recursive hierarchy This specification is related to: Open Data (OData) services expose a data model that describes the
-schema of the service in terms of the Entity Data Model (EDM, see OData-CSDL) and then allows for querying data in
-terms of this model. The responses returned by an OData service are
-based on that data model and retain the relationships between the
-entities in the model. Open Data Protocol (OData) services expose a data model that
+describes the schema of the service in terms of the Entity Data Model
+(EDM, see OData-CSDL) and then allows for
+querying data in terms of this model. The responses returned by an OData
+service are based on that data model and retain the relationships
+between the entities in the model. Extending the OData query features with simple aggregation
capabilities avoids cluttering OData services with an exponential number
of explicitly modeled "aggregation level entities" or else restricting
@@ -1091,18 +1096,18 @@ The Amount property in the Sale entity type is an aggregatable property, and the
-properties of the related entity types are groupable. These can be
+ The Query extensions and descriptive annotations can both be applied to
-normalized as well as partly or fully denormalized schemas. Query extensions and descriptive annotations can be applied to
+normalized schemas as well as partly or fully denormalized schemas. Example 3: The following diagram depicts a denormalized schema for
the simple model. The system query option During serialization of the result of During serialization of the result of (The definitions of italicized terms made in this section are used
-throughout this text, always with a hyperlink to this section.) The definitions of italicized terms made in this section are used
+throughout this text, always with a hyperlink to this section. Here is an overview of the structural changes made by different
transformations: This document specifies when a data
+ This document specifies how a data
aggregation path that occurs in a request is evaluated by the
service. If such an evaluation fails, the service MUST reject the
request. Besides changes to the structural properties of the entities in a
+hierarchical collection, hierarchy maintenance involves changes to the
+parent-child relationships. Example 110: Move a sales organization Switzerland under the parent
+EMEA Central by setting the reference OData-Protocol section 11.4.6.3 of the parent
+navigation property target OData-URL, section
+4.4 to a reference to EMEA Central OData-JSON,
+section 14: results in Example 111: If the parent navigation property contained a
+referential constraint for the key of the target OData-CSDL, section 8.5, then alternatively the property taking part in the referential
+constraint OData-Protocol, section 11.4.9.1
+could be changed to EMEA Central: An entity set where the key property ⚠ Example 112: Given the following types of
+ the orphans can appear as descendants: results in An analogous request for the descendants of Atlantis would fail
+because of the cycle. Mars, Phobos and Phobos South Pole can be made descendants of the
+root node by giving Mars a node identifier: An attempt to make the island orphan Atlantis a child of the root
+node fails, because it would introduce cycles into the hierarchy. Applying aggregation first covers the most prominent use cases. The
slightly more sophisticated question "how much money is earned with
@@ -6341,39 +6485,39 @@ RecursiveHierarchy/ParentNavigationProperty
. The remainder
-of this section describes the case where it is collection-valued. The
-function \(ρ(c,x)\) used below
-constructs a path-to-the-root and was defined in the RecursiveHierarchy/ParentNavigationProperty with the standard definition for root. The
+remainder of this section describes the general case. The function \(ρ(c,x)\) used below constructs a
+path-to-the-root and was defined in the traverse
section.5.5
edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"
< Version="4.0">
-edmx:Reference Uri="http://docs.oasis-open.org/odata/odata-data-aggregation-ext/v4.0/cs01/vocabularies/Org.OData.Aggregation.V1.xml">
- <edmx:Include Alias="Aggregation"
- < Namespace="Org.OData.Aggregation.V1" />
-edmx:Reference>
- </edmx:DataServices>
- <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm"
- < Alias="SalesModel" Namespace="org.example.odata.salesservice">
-Annotations Target="SalesModel.Product">
- <Annotation Term="Aggregation.LeveledHierarchy"
- < Qualifier="ProductHierarchy">
-Collection>
- <PropertyPath>Category/Name</PropertyPath>
- <PropertyPath>Name</PropertyPath>
- <Collection>
- </Annotation>
- </Annotations>
- </
-Annotations Target="SalesModel.Time">
- <Annotation Term="Aggregation.LeveledHierarchy"
- < Qualifier="TimeHierarchy">
-Collection>
- <PropertyPath>Year</PropertyPath>
- <PropertyPath>Quarter</PropertyPath>
- <PropertyPath>Month</PropertyPath>
- <Collection>
- </Annotation>
- </Annotations>
- </
-Annotations Target="SalesModel.SalesOrganization">
- <Annotation Term="Aggregation.RecursiveHierarchy"
- < Qualifier="SalesOrgHierarchy">
-Record>
- <PropertyValue Property="NodeProperty"
- < PropertyPath="ID" />
-PropertyValue Property="ParentNavigationProperty"
- < PropertyPath="Superordinate" />
-PropertyValue Property="IsRoot">
- <Eq>
- <Path>Superordinate</Path>
- <Null />
- <Eq>
- </PropertyValue>
- </Record>
- </Annotation>
- </Annotations>
- </Schema>
- </edmx:DataServices>
- </edmx:Edmx> </
SalesOrgHierarchy
can be used in
functions with the $filter
system query option.Additional
Related work:
1.1
Type – a primitive type other than
Edm.Stream
or
subtypes of Edm.Geography
or Edm.Geometry
/
). Segments are names of declared or dynamic
+structural or navigation properties, or type-cast segments consisting of
+the (optionally qualified) name of a structured type that is derived
+from the type identified by the preceding path segment to reach
+properties declared by the derived type.
commonExpr
rule (see OData-ABNF)1.1
2
Overview
-2
-
Amount
property in the Sale
entity type
+is an aggregatable property, and
+the properties of the related entity types are groupable. These can be
arranged in four hierarchies:Category
and Product
entity types
+Country
and Customer
Year
, Month
, and Date
2
and three "dimensions". This document will avoid such terms, as they are
heavily overloaded.
2.2
transformation. The output set of the last set transformation in the
transformation sequence invoked by the system query option
$apply
is the result of $apply
. This is
-consistent with the use of service-defined bindable and composable
+consistent with the use of service-defined bound and composable
functions in path segments.
$apply
MUST NOT be used if the
resource path addresses a single instance.2.2
the plain-text number of items in the result of
$apply
.
This is similar to the combination of /$count
and
$filter
.
-$apply
, declared
+$apply
declared
properties and dynamic properties are represented as defined by the
response format. Other properties have been aggregated away and are not
represented in the response. The entities returned in the request
@@ -1823,8 +1828,8 @@ 2.2
3.1
Fundamentals of Input and Output Sets
-3.1.1
Type, Structure and Context URL
@@ -1861,11 +1866,12 @@ 2.2
properties that occurred in the input set.
2.2
3.1.3
Evaluation of Data Aggregation Paths
-Table of Contents
Aggregation per Rollup Level2.2
service MUST merge them into one occurrence in \(E\) if they are complementary and MUST
reject the request if they are contradictory. (See example 119.) If example 122.) If multiple occurrences of the same transient
entity are reached, the service MUST keep only one occurrence in
\(E\).
@@ -6332,7 +6334,149 @@
7.4
changing the result.
7.9
+id="79-maintaining-recursive-hierarchies">7.9
+Maintaining Recursive Hierarchies
+PUT /service/SalesOrganizations('Switzerland')/Superordinate/$ref
+Content-Type: application/json
+
+{ "@odata.id": "SalesOrganizations('EMEA Central')" }
204 No Content
.EntityType Name="SalesOrganization">
+ <Key>
+ <PropertyRef Name="ID" />
+ <Key>
+ </Property Name="ID" Type="Edm.String" Nullable="false" />
+ <Property Name="Name" Type="Edm.String" />
+ <Property Name="SuperordinateID" Type="Edm.String" />
+ <NavigationProperty Name="Superordinate"
+ < Type="SalesModel.SalesOrganization">
+ReferentialConstraint Property="SuperordinateID"
+ < ReferencedProperty="ID" />
+NavigationProperty>
+ </EntityType> </
PATCH /service/SalesOrganizations('Switzerland')
+Content-Type: application/json
+
+{ "SuperordinateID": "EMEA Central" }
ID
differs from the
+node identfier property NodeID
can contain entities without
+node identifier. And by using a non-standard definition of root, even nodes
+with node identifier can be unreachable from any root, these are called
+orphans.SalesOrganizations
and if only Sales is a root,
+
+
+
+
+
+
+Type
+ID
+NodeID
+SuperordinateID
+
+
+root node
+Sales
+Sales
+
+
+
+parent node
+EMEA
+EMEA
+Sales
+
+
+child node
+EMEA Central
+EMEA Central
+EMEA
+
+
+not a node
+Mars
+
+ Sales
+
+
+true orphan
+Phobos
+Phobos
+Mars
+
+
+true orphan
+Phobos South Pole
+Phobos South Pole
+Phobos
+
+
+unreachable orphan
+Venus
+Venus
+
+
+
+
+island orphan
+Atlantis
+Atlantis
+Atlantis
+
+GET /service/SalesOrganizations?$apply=descendants(
+ $root/SalesOrganizations,SalesOrgHierarchy,NodeID,
+ filter(ID eq 'Phobos'),keep start)
+ &$select=ID
{
+"@odata.context": "$metadata#SalesOrganizations(ID)",
+ "value": [
+ { "ID": "Phobos" },
+ { "ID": "Phobos South Pole" }
+ ]
+ }
PATCH /service/SalesOrganizations('Mars')
+Content-Type: application/json
+
+{ "NodeID": "Mars" }
7.10
Transformation Sequences
7.4
be specified in
$apply
in the order they are to be applied,
separated by a forward slash.
Example 110:
+Example 113:
GET /service/Sales?$apply=filter(Amount le 1)
/aggregate(Amount with sum as Total)
means "filter first, then aggregate", and results in
-{
-"@odata.context": "$metadata#Sales(Total)",
- "value": [
- { "Total@odata.type": "Decimal", "Total": 2 }
- ]
- }
{
+"@odata.context": "$metadata#Sales(Total)",
+ "value": [
+ { "Total@odata.type": "Decimal", "Total": 2 }
+ ]
+ }
Using filter
within $apply
does not
preclude using it as a normal system query option.
Example 111:
+Example 114:
GET /service/Sales?$apply=filter(Amount le 2)/groupby((Product/Name),
aggregate(Amount with sum as Total))
&$filter=Total ge 4
results in
-{
-"@odata.context": "$metadata#Sales(Product(Name),Total)",
- "value": [
- { "Product": { "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 4 },
- { "Product": { "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 4 }
- ]
- }
{
+"@odata.context": "$metadata#Sales(Product(Name),Total)",
+ "value": [
+ { "Product": { "Name": "Paper" },
+ "Total@odata.type": "Decimal", "Total": 4 },
+ { "Product": { "Name": "Sugar" },
+ "Total@odata.type": "Decimal", "Total": 4 }
+ ]
+ }
Example 112: Revisiting example 16 for using the +
Example 115: Revisiting example 16 for using the
from
keyword with the aggregate
function, the
request
GET /service/Sales?$apply=aggregate(Amount from Time with average
@@ -6387,31 +6531,31 @@ 7.4
sets for cities, countries and continents and the obvious associations
between them.
-Example 113: getting the population per country with
+Example 116: getting the population per country with
GET /service/Cities?$apply=groupby((Continent/Name,Country/Name),
aggregate(Population with sum as TotalPopulation))
results in
-{
-"@odata.context": "$metadata#Cities(Continent(Name),Country(Name),
- TotalPopulation)",
-"value": [
- { "Continent": { "Name": "Asia" }, "Country": { "Name": "China" },
- "TotalPopulation@odata.type": "Int32", "TotalPopulation": 1412000000 },
- { "Continent": { "Name": "Asia" }, "Country": { "Name": "India" },
- "TotalPopulation@odata.type": "Int32", "TotalPopulation": 1408000000 },
- ...
- ]
- }
+{
+"@odata.context": "$metadata#Cities(Continent(Name),Country(Name),
+ TotalPopulation)",
+"value": [
+ { "Continent": { "Name": "Asia" }, "Country": { "Name": "China" },
+ "TotalPopulation@odata.type": "Int32", "TotalPopulation": 1412000000 },
+ { "Continent": { "Name": "Asia" }, "Country": { "Name": "India" },
+ "TotalPopulation@odata.type": "Int32", "TotalPopulation": 1408000000 },
+ ...
+ ]
+ }
-Example 114: all countries with megacities and their continents
+Example 117: all countries with megacities and their continents
GET /service/Cities?$apply=filter(Population ge 10000000)
/groupby((Continent/Name,Country/Name),
aggregate(Population with sum as TotalPopulation))
-Example 115: all countries with tens of millions of city dwellers and
+
Example 118: all countries with tens of millions of city dwellers and
the continents only for these countries
GET /service/Cities?$apply=groupby((Continent/Name,Country/Name),
aggregate(Population with sum as CountryPopulation))
@@ -6429,7 +6573,7 @@ 7.4
as TotalPopulation))
-Example 116: all countries with tens of millions of city dwellers and
+
Example 119: all countries with tens of millions of city dwellers and
all continents with cities independent of their size
GET /service/Cities?$apply=groupby((Continent/Name,Country/Name),
aggregate(Population with sum as CountryPopulation))
@@ -6439,7 +6583,7 @@ 7.4
as TotalPopulation)))
-Example 117: assuming the data model includes a sales order entity
+
Example 120: assuming the data model includes a sales order entity
set with related sets for order items and customers, the base set as
well as the related items can be filtered before aggregation
GET /service/SalesOrders?$apply=filter(Status eq 'incomplete')
@@ -6448,7 +6592,7 @@ 7.4
aggregate(FilteredItems/Amount with sum as ItemAmount))
-Example 118: assuming that Amount
is a custom aggregate
+
Example 121: assuming that Amount
is a custom aggregate
in addition to the property, determine the total for countries with an
Amount
greater than 1000
GET /service/SalesOrders?$apply=
@@ -6457,7 +6601,7 @@ 7.4
/aggregate(Amount)
-Example 119: The
+
Example 122: The
output set of the concat
transformation contains
Sales
entities multiple times with conflicting related
AugmentedProduct
entities that cannot be aggregated by the
@@ -6469,28 +6613,28 @@
7.4
results in an error.
-Example 120: The nest
transformation can be used inside
+
Example 123: The nest
transformation can be used inside
groupby
to produce one or more collection-valued properties
per group.
GET /service/Sales?$apply=groupby((Product/Category/ID),
nest(groupby((Customer/ID)) as Customers))
results in
-{
-"@odata.context":"$metadata#Sales(Product(Category(ID)),Customers())",
- "value": [
- { "Product": { "Category": { "ID": "PG1" } },
- "Customers@odata.context": "#Sales(Customer(ID))",
- "Customers": [ { "Customer": { "ID": "C1" } },
- { "Customer": { "ID": "C2" } },
- { "Customer": { "ID": "C3" } } ] },
- { "Product": { "Category": { "ID": "PG2" } },
- "Customers@odata.context": "#Sales(Customer(ID))",
- "Customers": [ { "Customer": { "ID": "C1" } },
- { "Customer": { "ID": "C2" } },
- { "Customer": { "ID": "C3" } } ] }
- ]
- }
+{
+"@odata.context":"$metadata#Sales(Product(Category(ID)),Customers())",
+ "value": [
+ { "Product": { "Category": { "ID": "PG1" } },
+ "Customers@odata.context": "#Sales(Customer(ID))",
+ "Customers": [ { "Customer": { "ID": "C1" } },
+ { "Customer": { "ID": "C2" } },
+ { "Customer": { "ID": "C3" } } ] },
+ { "Product": { "Category": { "ID": "PG2" } },
+ "Customers@odata.context": "#Sales(Customer(ID))",
+ "Customers": [ { "Customer": { "ID": "C1" } },
+ { "Customer": { "ID": "C2" } },
+ { "Customer": { "ID": "C3" } } ] }
+ ]
+ }
8
diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
index 8c262c53f..bd1e7799f 100644
--- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
+++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
@@ -178,7 +178,8 @@ For complete copyright information please see the full Notices section in an App
- [7.6 Model Functions as Set Transformations](#ModelFunctionsasSetTransformations)
- [7.7 Controlling Aggregation per Rollup Level](#ControllingAggregationperRollupLevel)
- [7.8 Aggregation in Recursive Hierarchies](#AggregationinRecursiveHierarchies)
- - [7.9 Transformation Sequences](#TransformationSequences)
+ - [7.9 Maintaining Recursive Hierarchies](#MaintainingRecursiveHierarchies)
+ - [7.10 Transformation Sequences](#TransformationSequences)
- [8 Conformance](#Conformance)
- [A References](#References)
- [A.1 Normative References](#NormativeReferences)
@@ -1122,7 +1123,7 @@ _Determination of $U$:_
Let $I$ be the input set. If $p$ is absent, let $U=I$ with null values removed.
Otherwise, let $q$ be the portion of $p$ up to and including the last navigation property, if any, and any type-cast segment that immediately follows, and let $r$ be the remainder, if any, of $p$ that contains no navigation properties, such that $p$ equals the concatenated path $q⁄r$. The aggregate transformation considers each entity reached via the path $q$ exactly once. To this end, using the [$\Gamma$ notation](#EvaluationofDataAggregationPaths):
-- If $q$ is non-empty, let $E=\Gamma(I,q)$ and remove duplicates from that entity collection: If [multiple representations of the same non-transient entity](#SamenessandPrecedence) are reached, the service MUST merge them into one occurrence in $E$ if they are complementary and MUST reject the request if they are contradictory. (See [example 119](#aggrconflict).) If [multiple occurrences of the same transient entity](#SamenessandPrecedence) are reached, the service MUST keep only one occurrence in $E$.
+- If $q$ is non-empty, let $E=\Gamma(I,q)$ and remove duplicates from that entity collection: If [multiple representations of the same non-transient entity](#SamenessandPrecedence) are reached, the service MUST merge them into one occurrence in $E$ if they are complementary and MUST reject the request if they are contradictory. (See [example 122](#aggrconflict).) If [multiple occurrences of the same transient entity](#SamenessandPrecedence) are reached, the service MUST keep only one occurrence in $E$.
- If $q$ is empty, let $E=I$.
Then, if $r$ is empty, let $U=E$, otherwise let $U=\Gamma(E,r)$, this consists of instances or primitive values, possibly with repetitions.
@@ -4317,12 +4318,100 @@ GET /service/Sales?$apply=groupby((rolluprecursive(
`traverse` acts here as a filter, hence `preorder` could be changed to `postorder` without changing the result.
:::
-## 7.9 Transformation Sequences
+## 7.9 Maintaining Recursive Hierarchies
+
+Besides changes to the structural properties of the entities in a hierarchical collection, hierarchy maintenance involves changes to the parent-child relationships.
+
+::: example
+Example 110: Move a sales organization Switzerland under the parent EMEA Central by setting the reference [OData-Protocol section 11.4.6.3](#ODataProtocol) of the parent navigation property target [OData-URL, section 4.4](#ODataURL) to a reference to EMEA Central [OData-JSON, section 14](#ODataJSON):
+```json
+PUT /service/SalesOrganizations('Switzerland')/Superordinate/$ref
+Content-Type: application/json
+
+{ "@odata.id": "SalesOrganizations('EMEA Central')" }
+```
+results in `204 No Content`.
+:::
+
+::: example
+Example 111: If the parent navigation property contained a referential constraint for the key of the target [OData-CSDL, section 8.5](#ODataCSDL),
+```xml
+
+
+
+
+
+
+
+
+
+
+
+```
+then alternatively the property taking part in the referential constraint [OData-Protocol, section 11.4.9.1](#ODataProtocol) could be changed to EMEA Central:
+```json
+PATCH /service/SalesOrganizations('Switzerland')
+Content-Type: application/json
+
+{ "SuperordinateID": "EMEA Central" }
+```
+:::
+
+An entity set where the key property `ID` differs from the node identfier property `NodeID` can contain entities without node identifier. And by using a non-[standard definition of root](#RecursiveHierarchy), even nodes with node identifier can be unreachable from any root, these are called orphans.
+
+::: example
+⚠ Example 112: Given the following types of `SalesOrganizations` and if only Sales is a root,
+
+Type|ID|NodeID|SuperordinateID
+----|--|------|---------------
+root node|Sales|Sales|
+parent node|EMEA|EMEA|Sales
+child node|EMEA Central|EMEA Central|EMEA
+not a node|Mars||Sales
+true orphan|Phobos|Phobos|Mars
+true orphan|Phobos South Pole|Phobos South Pole|Phobos
+unreachable orphan|Venus|Venus|
+island orphan|Atlantis|Atlantis|Atlantis
+
+the orphans can appear as descendants:
+```
+GET /service/SalesOrganizations?$apply=descendants(
+ $root/SalesOrganizations,SalesOrgHierarchy,NodeID,
+ filter(ID eq 'Phobos'),keep start)
+ &$select=ID
+```
+results in
+```json
+{
+ "@odata.context": "$metadata#SalesOrganizations(ID)",
+ "value": [
+ { "ID": "Phobos" },
+ { "ID": "Phobos South Pole" }
+ ]
+}
+```
+
+An analogous request for the descendants of Atlantis would fail because of the cycle.
+
+Mars, Phobos and Phobos South Pole can be made descendants of the root node by giving Mars a node identifier:
+```json
+PATCH /service/SalesOrganizations('Mars')
+Content-Type: application/json
+
+{ "NodeID": "Mars" }
+```
+
+An attempt to make the island orphan Atlantis a child of the root node fails, because it would introduce cycles into the hierarchy.
+:::
+
+## 7.10 Transformation Sequences
Applying aggregation first covers the most prominent use cases. The slightly more sophisticated question "how much money is earned with small sales" requires filtering the base set before applying the aggregation. To enable this type of question several transformations can be specified in `$apply` in the order they are to be applied, separated by a forward slash.
::: example
-Example 110:
+Example 113:
```
GET /service/Sales?$apply=filter(Amount le 1)
/aggregate(Amount with sum as Total)
@@ -4341,7 +4430,7 @@ means "filter first, then aggregate", and results in
Using `filter` within `$apply` does not preclude using it as a normal system query option.
::: example
-Example 111:
+Example 114:
```
GET /service/Sales?$apply=filter(Amount le 2)/groupby((Product/Name),
aggregate(Amount with sum as Total))
@@ -4362,7 +4451,7 @@ results in
:::
::: example
-Example 112: Revisiting [example 16](#from) for using the `from` keyword with the `aggregate` function, the request
+Example 115: Revisiting [example 16](#from) for using the `from` keyword with the `aggregate` function, the request
```
GET /service/Sales?$apply=aggregate(Amount from Time with average
as DailyAverage)
@@ -4376,7 +4465,7 @@ GET /service/Sales?$apply=groupby((Time),aggregate(Amount with sum as Total))
For further examples, consider another data model containing entity sets for cities, countries and continents and the obvious associations between them.
::: example
-Example 113: getting the population per country with
+Example 116: getting the population per country with
```
GET /service/Cities?$apply=groupby((Continent/Name,Country/Name),
aggregate(Population with sum as TotalPopulation))
@@ -4398,7 +4487,7 @@ results in
:::
::: example
-Example 114: all countries with megacities and their continents
+Example 117: all countries with megacities and their continents
```
GET /service/Cities?$apply=filter(Population ge 10000000)
/groupby((Continent/Name,Country/Name),
@@ -4407,7 +4496,7 @@ GET /service/Cities?$apply=filter(Population ge 10000000)
:::
::: example
-Example 115: all countries with tens of millions of city dwellers and the continents only for these countries
+Example 118: all countries with tens of millions of city dwellers and the continents only for these countries
```
GET /service/Cities?$apply=groupby((Continent/Name,Country/Name),
aggregate(Population with sum as CountryPopulation))
@@ -4429,7 +4518,7 @@ GET /service/Cities?$apply=groupby((Continent/Name,Country/Name),
:::
::: example
-Example 116: all countries with tens of millions of city dwellers and all continents with cities independent of their size
+Example 119: all countries with tens of millions of city dwellers and all continents with cities independent of their size
```
GET /service/Cities?$apply=groupby((Continent/Name,Country/Name),
aggregate(Population with sum as CountryPopulation))
@@ -4441,7 +4530,7 @@ GET /service/Cities?$apply=groupby((Continent/Name,Country/Name),
:::
::: example
-Example 117: assuming the data model includes a sales order entity set with related sets for order items and customers, the base set as well as the related items can be filtered before aggregation
+Example 120: assuming the data model includes a sales order entity set with related sets for order items and customers, the base set as well as the related items can be filtered before aggregation
```
GET /service/SalesOrders?$apply=filter(Status eq 'incomplete')
/addnested(Items,filter(not Shipped) as FilteredItems)
@@ -4451,7 +4540,7 @@ GET /service/SalesOrders?$apply=filter(Status eq 'incomplete')
:::
::: example
-Example 118: assuming that `Amount` is a custom aggregate in addition to the property, determine the total for countries with an `Amount` greater than 1000
+Example 121: assuming that `Amount` is a custom aggregate in addition to the property, determine the total for countries with an `Amount` greater than 1000
```
GET /service/SalesOrders?$apply=
groupby((Customer/Country),aggregate(Amount))
@@ -4461,7 +4550,7 @@ GET /service/SalesOrders?$apply=
:::
::: example
-Example 119: The output set of the `concat` transformation contains `Sales` entities multiple times with conflicting related `AugmentedProduct` entities that cannot be aggregated by the second transformation.
+Example 122: The output set of the `concat` transformation contains `Sales` entities multiple times with conflicting related `AugmentedProduct` entities that cannot be aggregated by the second transformation.
```
GET /service/Sales?$apply=
concat(addnested(Product,compute(0.1 as Discount) as AugmentedProduct),
@@ -4472,7 +4561,7 @@ results in an error.
:::
::: example
-Example 120: The `nest` transformation can be used inside `groupby` to produce one or more collection-valued properties per group.
+Example 123: The `nest` transformation can be used inside `groupby` to produce one or more collection-valued properties per group.
```
GET /service/Sales?$apply=groupby((Product/Category/ID),
nest(groupby((Customer/ID)) as Customers))
diff --git a/odata-data-aggregation-ext/7 Examples.md b/odata-data-aggregation-ext/7 Examples.md
index 6fcb7dfe1..36a83c9f8 100644
--- a/odata-data-aggregation-ext/7 Examples.md
+++ b/odata-data-aggregation-ext/7 Examples.md
@@ -1306,6 +1306,94 @@ GET /service/Sales?$apply=groupby((rolluprecursive(
`traverse` acts here as a filter, hence `preorder` could be changed to `postorder` without changing the result.
:::
+## ##subsec Maintaining Recursive Hierarchies
+
+Besides changes to the structural properties of the entities in a hierarchical collection, hierarchy maintenance involves changes to the parent-child relationships.
+
+::: example
+Example ##ex: Move a sales organization Switzerland under the parent EMEA Central by setting the reference [OData-Protocol section 11.4.6.3](#ODataProtocol) of the parent navigation property target [OData-URL, section 4.4](#ODataURL) to a reference to EMEA Central [OData-JSON, section 14](#ODataJSON):
+```json
+PUT /service/SalesOrganizations('Switzerland')/Superordinate/$ref
+Content-Type: application/json
+
+{ "@odata.id": "SalesOrganizations('EMEA Central')" }
+```
+results in `204 No Content`.
+:::
+
+::: example
+Example ##ex: If the parent navigation property contained a referential constraint for the key of the target [OData-CSDL, section 8.5](#ODataCSDL),
+```xml
+
+
+
+
+
+
+
+
+
+
+
+```
+then alternatively the property taking part in the referential constraint [OData-Protocol, section 11.4.9.1](#ODataProtocol) could be changed to EMEA Central:
+```json
+PATCH /service/SalesOrganizations('Switzerland')
+Content-Type: application/json
+
+{ "SuperordinateID": "EMEA Central" }
+```
+:::
+
+An entity set where the key property `ID` differs from the node identfier property `NodeID` can contain entities without node identifier. And by using a non-[standard definition of root](#RecursiveHierarchy), even nodes with node identifier can be unreachable from any root, these are called orphans.
+
+::: example
+⚠ Example ##ex: Given the following types of `SalesOrganizations` and if only Sales is a root,
+
+Type|ID|NodeID|SuperordinateID
+----|--|------|---------------
+root node|Sales|Sales|
+parent node|EMEA|EMEA|Sales
+child node|EMEA Central|EMEA Central|EMEA
+not a node|Mars||Sales
+true orphan|Phobos|Phobos|Mars
+true orphan|Phobos South Pole|Phobos South Pole|Phobos
+unreachable orphan|Venus|Venus|
+island orphan|Atlantis|Atlantis|Atlantis
+
+the orphans can appear as descendants:
+```
+GET /service/SalesOrganizations?$apply=descendants(
+ $root/SalesOrganizations,SalesOrgHierarchy,NodeID,
+ filter(ID eq 'Phobos'),keep start)
+ &$select=ID
+```
+results in
+```json
+{
+ "@odata.context": "$metadata#SalesOrganizations(ID)",
+ "value": [
+ { "ID": "Phobos" },
+ { "ID": "Phobos South Pole" }
+ ]
+}
+```
+
+An analogous request for the descendants of Atlantis would fail because of the cycle.
+
+Mars, Phobos and Phobos South Pole can be made descendants of the root node by giving Mars a node identifier:
+```json
+PATCH /service/SalesOrganizations('Mars')
+Content-Type: application/json
+
+{ "NodeID": "Mars" }
+```
+
+An attempt to make the island orphan Atlantis a child of the root node fails, because it would introduce cycles into the hierarchy.
+:::
+
## ##subsec Transformation Sequences
Applying aggregation first covers the most prominent use cases. The slightly more sophisticated question "how much money is earned with small sales" requires filtering the base set before applying the aggregation. To enable this type of question several transformations can be specified in `$apply` in the order they are to be applied, separated by a forward slash.
From 9acc7b30f71440975fec674c98eeba1ec315e073 Mon Sep 17 00:00:00 2001
From: D024504
Date: Fri, 26 May 2023 08:17:46 +0200
Subject: [PATCH 015/116] fine-tuning
---
.../odata-data-aggregation-ext.html | 4 ++--
docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md | 2 +-
odata-data-aggregation-ext/1 Introduction.md | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
index d7fff90e3..7d84b50b2 100644
--- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
+++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
@@ -511,8 +511,8 @@ 1.1
collection
\(u,v,w\) – instances in a
collection
-\(x,y\) – instances in a
-hierarchical collection, called nodes
+\(x\) – an instance in a
+hierarchical collection, called a node
\(p,q,r\) – paths
\(S,T\) – transformation
sequences
diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
index e7627c781..51d714e7c 100644
--- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
+++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
@@ -217,7 +217,7 @@ The following non-exhaustive list contains variables that are used throughout th
- $A,B,C$ – collections of instances
- $H$ – hierarchical collection
- $u,v,w$ – instances in a collection
-- $x,y$ – instances in a hierarchical collection, called nodes
+- $x$ – an instance in a hierarchical collection, called a node
- $p,q,r$ – paths
- $S,T$ – transformation sequences
- $α$ – aggregate expression, defined [below](#AggregationAlgorithm)
diff --git a/odata-data-aggregation-ext/1 Introduction.md b/odata-data-aggregation-ext/1 Introduction.md
index 3af889c18..955352c2c 100644
--- a/odata-data-aggregation-ext/1 Introduction.md
+++ b/odata-data-aggregation-ext/1 Introduction.md
@@ -24,7 +24,7 @@ The following non-exhaustive list contains variables that are used throughout th
- $A,B,C$ – collections of instances
- $H$ – hierarchical collection
- $u,v,w$ – instances in a collection
-- $x,y$ – instances in a hierarchical collection, called nodes
+- $x$ – an instance in a hierarchical collection, called a node
- $p,q,r$ – paths
- $S,T$ – transformation sequences
- $α$ – aggregate expression, defined [below](#AggregationAlgorithm)
From b4ae6d9569aabc874d57deb73da45a92fb49babf Mon Sep 17 00:00:00 2001
From: D024504
Date: Fri, 26 May 2023 08:11:56 +0200
Subject: [PATCH 016/116] fine-tuning
---
.../odata-data-aggregation-ext.html | 38 +++++++++----------
.../odata-data-aggregation-ext.md | 16 ++++----
.../6 Hierarchical Transformations.md | 6 +--
odata-data-aggregation-ext/7 Examples.md | 10 ++---
4 files changed, 35 insertions(+), 35 deletions(-)
diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
index 431c4bc0a..de8c1c2ab 100644
--- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
+++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
@@ -4772,17 +4772,24 @@ 5.5
root is injected into each \(σ(x)\) by
annotating \(x\) differently before
each \(σ(x)\) is computed.
-More precisely, an path-to-the-root is a node \(x\) that is annotated with the term
+
More precisely, a path-to-the-root is a node \(y\) that is annotated with the term
UpNode
from the Aggregation
vocabulary OData-VocAggr where the annotation value is the
-parent node \(y\) such that \(R(x)\) appears on the right-hand side of
-the recursive formula for \(R(y)\). The
-annotation value \(y\) is again
+parent node \(x\) such that \(R(y)\) appears on the right-hand side of
+the recursive formula for \(R(x)\). The
+annotation value \(x\) is again
annotated with Aggregation.UpNode
and so on until a root is
reached. Every instance in the output set of traverse
is
related to one path-to-the-root.
+Given a path-to-the-root \(x\) and a
+child \(c\) of \(x\), let \(ρ(c,x)\) be the path-to-the-root consisting
+of the node \(c\) annotated with
+Aggregation.UpNode
and value \(x\).
The transformation \(\Pi_G(σ(x))\)
is extended with an additional step between steps 2 and 3 of the
function \(a_G(u,s,p)\) as defined in
@@ -4793,13 +4800,6 @@
5.5
class="math inline">\(s\) to \(u\).
-Given a path-to-the-root \(x\) and a
-child \(c\) of \(x\), let \(ρ(c,x)\) be the path-to-the-root consisting
-of the node \(c\) annotated with
-Aggregation.UpNode
and value \(x\).
The Aggregation.UpNode
annotation of a root has value
null. With \(r_1,…,r_n\) as above, the
transformation \({\tt
@@ -6389,7 +6389,7 @@ 7.4
orphans.
⚠ Example 112: Given the following types of
-SalesOrganizations
and if only Sales is a root,
+SalesOrganizations
where only Sales is a root,
@@ -6450,10 +6450,10 @@ 7.4
-the orphans can appear as descendants:
-GET /service/SalesOrganizations?$apply=descendants(
+the orphan nodes can appear as ancestors:
+GET /service/SalesOrganizations?$apply=ancestors(
$root/SalesOrganizations,SalesOrgHierarchy,NodeID,
- filter(ID eq 'Phobos'),keep start)
+ filter(ID eq 'Phobos South Pole'),keep start)
&$select=ID
results in
-An analogous request for the descendants of Atlantis would fail
-because of the cycle.
+An analogous request for the ancestors of Atlantis would fail because
+of the cycle.
Mars, Phobos and Phobos South Pole can be made descendants of the
root node by giving Mars a node identifier:
Date: Fri, 26 May 2023 09:48:26 +0200
Subject: [PATCH 017/116] extended example 109
---
.../odata-data-aggregation-ext.html | 150 +++++++++++-------
.../odata-data-aggregation-ext.md | 33 +++-
.../6 Hierarchical Transformations.md | 4 +-
odata-data-aggregation-ext/7 Examples.md | 29 +++-
4 files changed, 154 insertions(+), 62 deletions(-)
diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
index 7d84b50b2..195bc89c2 100644
--- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
+++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
@@ -5002,7 +5002,7 @@ 5.5
results in
{
-"@odata.context": "$metadata#Sales(SalesOrganization,
+ "@odata.context": "$metadata#Sales(SalesOrganization(),
TotalAmountIncl,TotalAmountExcl)",
"value": [
{ "SalesOrganization": { "ID": "US West", "Name": "US West" },
@@ -5034,7 +5034,7 @@ 5.5
results in
{
-"@odata.context": "$metadata#Sales(SalesOrganization,TotalAmount)",
+ "@odata.context": "$metadata#Sales(SalesOrganization(),TotalAmount)",
"value": [
{ "SalesOrganization": { "ID": "Sales", "Name": "Corporate Sales" },
"TotalAmount": null },
@@ -6287,13 +6287,39 @@ 7.4
}
-⚠ Example 109: Assuming an extension of the data model where a
+
⚠ Example 109: Assume an extension of the data model where a
SalesOrganization
is associated with one or more instances
of ProductCategory
, and ProductCategory
also
-organizes categories in a recursive hierarchy, aggregation of sales
-amounts along the sales organization hierarchy could be restricted to
-those organizations linked with product category "Car" or a descendant
-of it:
+organizes categories in a recursive hierarchy:
+
+
+
+ProductCategory
+parent ProductCategory
+associated SalesOrganizations
+
+
+
+
+Food
+
+US, EMEA
+
+
+Cereals
+Food
+US
+
+
+Organic cereals
+Cereals
+US West
+
+
+
+Aggregation of sales amounts along the sales organization hierarchy
+could be restricted to those organizations linked with product category
+"Cereals" or a descendant of it:
GET /service/Sales?$apply=groupby((rolluprecursive(
$root/SalesOrganizations,SalesOrgHierarchy,
SalesOrganization/ID,
@@ -6307,11 +6333,27 @@ 7.4
descendants(
$root/ProductCategories,ProductCategoryHierarchy,
ID,
- filter(Name eq 'Car'),
+ filter(Name eq 'Cereals'),
keep start)),
keep start)
)),
- aggregate(Amount with sum as TotalAmount))
+ aggregate(Amount with sum as TotalAmount))
+ &$expand=SalesOrganization($select=ID,$expand=ProductCategories/$ref)
+results in
+{
+"@odata.context": "$metadata#Sales(SalesOrganization(ID),TotalAmount)",
+ "value": [
+ { "SalesOrganization": { "ID": "Sales", "ProductCategories": [ ] },
+ "TotalAmount@odata.type": "Decimal", "TotalAmount": 24 },
+ { "SalesOrganization": { "ID": "US", "ProductCategories": [
+ { "@odata.id": "ProductCategories('Cereals')" } ] },
+ "TotalAmount@odata.type": "Decimal", "TotalAmount": 19 },
+ { "SalesOrganization": { "ID": "US West", "ProductCategories": [
+ { "@odata.id": "ProductCategories('Organic cereals')" } ] },
+ "TotalAmount@odata.type": "Decimal", "TotalAmount": 7 }
+ ]
+ }
traverse
acts here as a filter, hence
preorder
could be changed to postorder
without
changing the result.
@@ -6330,13 +6372,13 @@ 7.4
GET /service/Sales?$apply=filter(Amount le 1)
/aggregate(Amount with sum as Total)
means "filter first, then aggregate", and results in
-{
-"@odata.context": "$metadata#Sales(Total)",
- "value": [
- { "Total@odata.type": "Decimal", "Total": 2 }
- ]
- }
+{
+"@odata.context": "$metadata#Sales(Total)",
+ "value": [
+ { "Total@odata.type": "Decimal", "Total": 2 }
+ ]
+ }
Using filter
within $apply
does not
preclude using it as a normal system query option.
@@ -6346,16 +6388,16 @@ 7.4
aggregate(Amount with sum as Total))
&$filter=Total ge 4
results in
-{
-"@odata.context": "$metadata#Sales(Product(Name),Total)",
- "value": [
- { "Product": { "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 4 },
- { "Product": { "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 4 }
- ]
- }
+{
+"@odata.context": "$metadata#Sales(Product(Name),Total)",
+ "value": [
+ { "Product": { "Name": "Paper" },
+ "Total@odata.type": "Decimal", "Total": 4 },
+ { "Product": { "Name": "Sugar" },
+ "Total@odata.type": "Decimal", "Total": 4 }
+ ]
+ }
Example 112: Revisiting example 16 for using the
@@ -6376,18 +6418,18 @@
7.4
GET /service/Cities?$apply=groupby((Continent/Name,Country/Name),
aggregate(Population with sum as TotalPopulation))
results in
-{
-"@odata.context": "$metadata#Cities(Continent(Name),Country(Name),
- TotalPopulation)",
-"value": [
- { "Continent": { "Name": "Asia" }, "Country": { "Name": "China" },
- "TotalPopulation@odata.type": "Int32", "TotalPopulation": 1412000000 },
- { "Continent": { "Name": "Asia" }, "Country": { "Name": "India" },
- "TotalPopulation@odata.type": "Int32", "TotalPopulation": 1408000000 },
- ...
- ]
- }
+{
+"@odata.context": "$metadata#Cities(Continent(Name),Country(Name),
+ TotalPopulation)",
+"value": [
+ { "Continent": { "Name": "Asia" }, "Country": { "Name": "China" },
+ "TotalPopulation@odata.type": "Int32", "TotalPopulation": 1412000000 },
+ { "Continent": { "Name": "Asia" }, "Country": { "Name": "India" },
+ "TotalPopulation@odata.type": "Int32", "TotalPopulation": 1408000000 },
+ ...
+ ]
+ }
8
diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
index 51d714e7c..1f5022a9c 100644
--- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
+++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
@@ -2951,7 +2951,7 @@ GET /service/Sales?$apply=groupby(
results in
```json
{
- "@odata.context": "$metadata#Sales(SalesOrganization,
+ "@odata.context": "$metadata#Sales(SalesOrganization(),
TotalAmountIncl,TotalAmountExcl)",
"value": [
{ "SalesOrganization": { "ID": "US West", "Name": "US West" },
@@ -2979,7 +2979,7 @@ GET /service/Sales?$apply=
results in
```json
{
- "@odata.context": "$metadata#Sales(SalesOrganization,TotalAmount)",
+ "@odata.context": "$metadata#Sales(SalesOrganization(),TotalAmount)",
"value": [
{ "SalesOrganization": { "ID": "Sales", "Name": "Corporate Sales" },
"TotalAmount": null },
@@ -4286,7 +4286,15 @@ results in
:::
::: example
-⚠ Example 109: Assuming an extension of the data model where a `SalesOrganization` is associated with one or more instances of `ProductCategory`, and `ProductCategory` also organizes categories in a recursive hierarchy, aggregation of sales amounts along the sales organization hierarchy could be restricted to those organizations linked with product category "Car" or a descendant of it:
+⚠ Example 109: Assume an extension of the data model where a `SalesOrganization` is associated with one or more instances of `ProductCategory`, and `ProductCategory` also organizes categories in a recursive hierarchy:
+
+ProductCategory|parent ProductCategory|associated SalesOrganizations
+---------------|----------------------|-----------------------------
+Food||US, EMEA
+Cereals|Food|US
+Organic cereals|Cereals|US West
+
+Aggregation of sales amounts along the sales organization hierarchy could be restricted to those organizations linked with product category "Cereals" or a descendant of it:
```
GET /service/Sales?$apply=groupby((rolluprecursive(
$root/SalesOrganizations,SalesOrgHierarchy,
@@ -4301,11 +4309,28 @@ GET /service/Sales?$apply=groupby((rolluprecursive(
descendants(
$root/ProductCategories,ProductCategoryHierarchy,
ID,
- filter(Name eq 'Car'),
+ filter(Name eq 'Cereals'),
keep start)),
keep start)
)),
aggregate(Amount with sum as TotalAmount))
+ &$expand=SalesOrganization($select=ID,$expand=ProductCategories/$ref)
+```
+results in
+```json
+{
+ "@odata.context": "$metadata#Sales(SalesOrganization(ID),TotalAmount)",
+ "value": [
+ { "SalesOrganization": { "ID": "Sales", "ProductCategories": [ ] },
+ "TotalAmount@odata.type": "Decimal", "TotalAmount": 24 },
+ { "SalesOrganization": { "ID": "US", "ProductCategories": [
+ { "@odata.id": "ProductCategories('Cereals')" } ] },
+ "TotalAmount@odata.type": "Decimal", "TotalAmount": 19 },
+ { "SalesOrganization": { "ID": "US West", "ProductCategories": [
+ { "@odata.id": "ProductCategories('Organic cereals')" } ] },
+ "TotalAmount@odata.type": "Decimal", "TotalAmount": 7 }
+ ]
+}
```
`traverse` acts here as a filter, hence `preorder` could be changed to `postorder` without changing the result.
diff --git a/odata-data-aggregation-ext/6 Hierarchical Transformations.md b/odata-data-aggregation-ext/6 Hierarchical Transformations.md
index 3d799ab80..540920d96 100644
--- a/odata-data-aggregation-ext/6 Hierarchical Transformations.md
+++ b/odata-data-aggregation-ext/6 Hierarchical Transformations.md
@@ -415,7 +415,7 @@ GET /service/Sales?$apply=groupby(
results in
```json
{
- "@odata.context": "$metadata#Sales(SalesOrganization,
+ "@odata.context": "$metadata#Sales(SalesOrganization(),
TotalAmountIncl,TotalAmountExcl)",
"value": [
{ "SalesOrganization": { "ID": "US West", "Name": "US West" },
@@ -443,7 +443,7 @@ GET /service/Sales?$apply=
results in
```json
{
- "@odata.context": "$metadata#Sales(SalesOrganization,TotalAmount)",
+ "@odata.context": "$metadata#Sales(SalesOrganization(),TotalAmount)",
"value": [
{ "SalesOrganization": { "ID": "Sales", "Name": "Corporate Sales" },
"TotalAmount": null },
diff --git a/odata-data-aggregation-ext/7 Examples.md b/odata-data-aggregation-ext/7 Examples.md
index 5aa53ad39..32715bf91 100644
--- a/odata-data-aggregation-ext/7 Examples.md
+++ b/odata-data-aggregation-ext/7 Examples.md
@@ -1281,7 +1281,15 @@ results in
:::
::: example
-⚠ Example ##ex: Assuming an extension of the data model where a `SalesOrganization` is associated with one or more instances of `ProductCategory`, and `ProductCategory` also organizes categories in a recursive hierarchy, aggregation of sales amounts along the sales organization hierarchy could be restricted to those organizations linked with product category "Car" or a descendant of it:
+⚠ Example ##ex: Assume an extension of the data model where a `SalesOrganization` is associated with one or more instances of `ProductCategory`, and `ProductCategory` also organizes categories in a recursive hierarchy:
+
+ProductCategory|parent ProductCategory|associated SalesOrganizations
+---------------|----------------------|-----------------------------
+Food||US, EMEA
+Cereals|Food|US
+Organic cereals|Cereals|US West
+
+Aggregation of sales amounts along the sales organization hierarchy could be restricted to those organizations linked with product category "Cereals" or a descendant of it:
```
GET /service/Sales?$apply=groupby((rolluprecursive(
$root/SalesOrganizations,SalesOrgHierarchy,
@@ -1296,11 +1304,28 @@ GET /service/Sales?$apply=groupby((rolluprecursive(
descendants(
$root/ProductCategories,ProductCategoryHierarchy,
ID,
- filter(Name eq 'Car'),
+ filter(Name eq 'Cereals'),
keep start)),
keep start)
)),
aggregate(Amount with sum as TotalAmount))
+ &$expand=SalesOrganization($select=ID,$expand=ProductCategories/$ref)
+```
+results in
+```json
+{
+ "@odata.context": "$metadata#Sales(SalesOrganization(ID),TotalAmount)",
+ "value": [
+ { "SalesOrganization": { "ID": "Sales", "ProductCategories": [ ] },
+ "TotalAmount@odata.type": "Decimal", "TotalAmount": 24 },
+ { "SalesOrganization": { "ID": "US", "ProductCategories": [
+ { "@odata.id": "ProductCategories('Cereals')" } ] },
+ "TotalAmount@odata.type": "Decimal", "TotalAmount": 19 },
+ { "SalesOrganization": { "ID": "US West", "ProductCategories": [
+ { "@odata.id": "ProductCategories('Organic cereals')" } ] },
+ "TotalAmount@odata.type": "Decimal", "TotalAmount": 7 }
+ ]
+}
```
`traverse` acts here as a filter, hence `preorder` could be changed to `postorder` without changing the result.
From e193e06b478a08b346b64804bc056217fa7b759b Mon Sep 17 00:00:00 2001
From: D024504
Date: Fri, 26 May 2023 09:56:21 +0200
Subject: [PATCH 018/116] corrected example 109
---
.../odata-data-aggregation-ext.html | 119 ++++++++++--------
.../odata-data-aggregation-ext.md | 15 ++-
odata-data-aggregation-ext/7 Examples.md | 15 ++-
3 files changed, 94 insertions(+), 55 deletions(-)
diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
index 195bc89c2..3fe7053fb 100644
--- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
+++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
@@ -6347,16 +6347,29 @@ 7.4
{ "SalesOrganization": { "ID": "Sales", "ProductCategories": [ ] },
"TotalAmount@odata.type": "Decimal", "TotalAmount": 24 },
{ "SalesOrganization": { "ID": "US", "ProductCategories": [
- { "@odata.id": "ProductCategories('Cereals')" } ] },
- "TotalAmount@odata.type": "Decimal", "TotalAmount": 19 },
- { "SalesOrganization": { "ID": "US West", "ProductCategories": [
- { "@odata.id": "ProductCategories('Organic cereals')" } ] },
- "TotalAmount@odata.type": "Decimal", "TotalAmount": 7 }
- ]
- }
+{ "@odata.id": "ProductCategories('Food')" },
+ { "@odata.id": "ProductCategories('Cereals')" } ] },
+ "TotalAmount@odata.type": "Decimal", "TotalAmount": 19 },
+ { "SalesOrganization": { "ID": "US West", "ProductCategories": [
+ { "@odata.id": "ProductCategories('Organic cereals')" } ] },
+ "TotalAmount@odata.type": "Decimal", "TotalAmount": 7 }
+ ]
+ }
traverse
acts here as a filter, hence
preorder
could be changed to postorder
without
-changing the result.
traverse
was omitted, the
+transformation
+ancestors(
+ $root/SalesOrganizations,SalesOrgHierarchy,
+ ID,
+ descendants(
+ $root/ProductCategories,ProductCategoryHierarchy,
+ ProductCategories/ID,
+ filter(ProductCategories/any(c:c/Name eq 'Cereals')),
+ keep start),
+ keep start)
+would determine descendants of sales organizations for "Cereals" and +their ancestors, so US East would appear in the result.
GET /service/Sales?$apply=filter(Amount le 1)
/aggregate(Amount with sum as Total)
means "filter first, then aggregate", and results in
-{
-"@odata.context": "$metadata#Sales(Total)",
- "value": [
- { "Total@odata.type": "Decimal", "Total": 2 }
- ]
- }
{
+"@odata.context": "$metadata#Sales(Total)",
+ "value": [
+ { "Total@odata.type": "Decimal", "Total": 2 }
+ ]
+ }
Using filter
within $apply
does not
preclude using it as a normal system query option.
results in
-{
-"@odata.context": "$metadata#Sales(Product(Name),Total)",
- "value": [
- { "Product": { "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 4 },
- { "Product": { "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 4 }
- ]
- }
{
+"@odata.context": "$metadata#Sales(Product(Name),Total)",
+ "value": [
+ { "Product": { "Name": "Paper" },
+ "Total@odata.type": "Decimal", "Total": 4 },
+ { "Product": { "Name": "Sugar" },
+ "Total@odata.type": "Decimal", "Total": 4 }
+ ]
+ }
Example 112: Revisiting example 16 for using the @@ -6418,18 +6431,18 @@
GET /service/Cities?$apply=groupby((Continent/Name,Country/Name),
aggregate(Population with sum as TotalPopulation))
results in
-{
-"@odata.context": "$metadata#Cities(Continent(Name),Country(Name),
- TotalPopulation)",
-"value": [
- { "Continent": { "Name": "Asia" }, "Country": { "Name": "China" },
- "TotalPopulation@odata.type": "Int32", "TotalPopulation": 1412000000 },
- { "Continent": { "Name": "Asia" }, "Country": { "Name": "India" },
- "TotalPopulation@odata.type": "Int32", "TotalPopulation": 1408000000 },
- ...
- ]
- }
{
+"@odata.context": "$metadata#Cities(Continent(Name),Country(Name),
+ TotalPopulation)",
+"value": [
+ { "Continent": { "Name": "Asia" }, "Country": { "Name": "China" },
+ "TotalPopulation@odata.type": "Int32", "TotalPopulation": 1412000000 },
+ { "Continent": { "Name": "Asia" }, "Country": { "Name": "India" },
+ "TotalPopulation@odata.type": "Int32", "TotalPopulation": 1408000000 },
+ ...
+ ]
+ }
concat
groupby
The following non-exhaustive list contains variables that are used -throughout this document:
+The following non-exhaustive list contains variable names that are +used throughout this document:
This notation is extended to the case of an empty path \(e\) by setting \(\Gamma(A,e)=A\). Note every \(\Gamma(A,e)=A\). Note every instance \(u\) in \(\Gamma(A,p)\) occurs also in \(A\) or nested into 3.2.1.2 the structures imposed by the two transformation sequences.
groupby
The groupby
transformation takes one or two parameters
where the second is a list of set transformations, separated by forward
slashes to express that they are consecutively applied. If the second
@@ -6369,7 +6373,8 @@
would determine descendants of sales organizations for "Cereals" and -their ancestors, so US East would appear in the result.
+their ancestor sales organizations, so US East would appear in the +result.results in
{
-"@odata.context": "$metadata#Sales(Total, MxA)",
+ "@context": "$metadata#Sales(Total, MxA)",
"value": [
- { "Total@odata.type": "Decimal", "Total": 24,
- "MxA@odata.type": "Decimal", "MxA": 8 }
+ { "Total@type": "Decimal", "Total": 24,
+ "MxA@type": "Decimal", "MxA": 8 }
]
}
results in
{
-"@odata.context": "$metadata#Sales(Tax)",
+ "@context": "$metadata#Sales(Tax)",
"value": [
- { "Tax@odata.type": "Decimal", "Tax": 2.08 }
+ { "Tax@type": "Decimal", "Tax": 2.08 }
]
}
results in
{
-"@odata.context": "$metadata#Sales(Total)",
+ "@context": "$metadata#Sales(Total)",
"value": [
- { "Total@odata.type": "Decimal", "Total": 24 }
+ { "Total@type": "Decimal", "Total": 24 }
]
}
results in
{
-"@odata.context": "$metadata#Sales(MinAmount)",
+ "@context": "$metadata#Sales(MinAmount)",
"value": [
- { "MinAmount@odata.type": "Decimal", "MinAmount": 1 }
+ { "MinAmount@type": "Decimal", "MinAmount": 1 }
]
}
results in
{
-"@odata.context": "$metadata#Sales(MaxAmount)",
+ "@context": "$metadata#Sales(MaxAmount)",
"value": [
- { "MaxAmount@odata.type": "Decimal", "MaxAmount": 8 }
+ { "MaxAmount@type": "Decimal", "MaxAmount": 8 }
]
}
results in
{
-"@odata.context": "$metadata#Sales(AverageAmount)",
+ "@context": "$metadata#Sales(AverageAmount)",
"value": [
- { "AverageAmount@odata.type": "Decimal", "AverageAmount": 3.0 }
+ { "AverageAmount@type": "Decimal", "AverageAmount": 3.0 }
]
}
results in
{
-"@odata.context": "$metadata#Sales(DistinctProducts)",
+ "@context": "$metadata#Sales(DistinctProducts)",
"value": [
- { "DistinctProducts@odata.type": "Decimal", "DistinctProducts": 3 }
+ { "DistinctProducts@type": "Decimal", "DistinctProducts": 3 }
]
}
results in
{
-"@odata.context": "$metadata#Sales(Customer(Country),Total,ProductNames)",
+ "@context": "$metadata#Sales(Customer(Country),Total,ProductNames)",
"value": [
{ "Customer": { "Country": "Netherlands" },
- "Total@odata.type": "Decimal", "Total": 5,
+ "Total@type": "Decimal", "Total": 5,
"ProductNames": "Paper,Sugar" },
{ "Customer": { "Country": "USA" },
- "Total@odata.type": "Decimal", "Total": 19,
+ "Total@type": "Decimal", "Total": 19,
"ProductNames": "Coffee,Paper,Sugar" }
]
}
results in
{
-"@odata.context": "$metadata#Sales(SalesCount)",
+ "@context": "$metadata#Sales(SalesCount)",
"value": [
- { "SalesCount@odata.type": "Decimal", "SalesCount": 8 }
+ { "SalesCount@type": "Decimal", "SalesCount": 8 }
]
}
and results in the average sales volume per day
{
-"@odata.context": "$metadata#Sales(DailyAverage)",
+ "@context": "$metadata#Sales(DailyAverage)",
"value": [
- { "DailyAverage@odata.type": "Decimal", "DailyAverage": 3.428571428571429 }
+ { "DailyAverage@type": "Decimal", "DailyAverage": 3.428571428571429 }
]
}
results in
{
-"@odata.context": "$metadata#Sales(Amount)",
+ "@context": "$metadata#Sales(Amount)",
"value": [
{ "ID": 4, "Amount": 8 },
{ "ID": 3, "Amount": 4 },
@@ -2727,23 +2727,23 @@ 3.2.1.2
results in
{
-"@odata.context": "$metadata#Sales(Customer(Country),Product(Name),Total)",
+ "@context": "$metadata#Sales(Customer(Country),Product(Name),Total)",
"value": [
{ "Customer": { "Country": "Netherlands" },
"Product": { "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 3 },
+ "Total@type": "Decimal", "Total": 3 },
{ "Customer": { "Country": "Netherlands" },
"Product": { "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 2 },
+ "Total@type": "Decimal", "Total": 2 },
{ "Customer": { "Country": "USA" },
"Product": { "Name": "Coffee" },
- "Total@odata.type": "Decimal", "Total": 12 },
+ "Total@type": "Decimal", "Total": 12 },
{ "Customer": { "Country": "USA" },
"Product": { "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 5 },
+ "Total@type": "Decimal", "Total": 5 },
{ "Customer": { "Country": "USA" },
"Product": { "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 2 }
+ "Total@type": "Decimal", "Total": 2 }
]
}
results in
{
-"@odata.context": "$metadata#Sales(Product(Name),Amount)",
+ "@context": "$metadata#Sales(Product(Name),Amount)",
"value": [
{ "Product": { "Name": "Coffee" }, "Amount": 4 },
{ "Product": { "Name": "Coffee" }, "Amount": 8 },
@@ -2843,31 +2843,31 @@ 3.2.1.2
results in seven entities for the finest grouping level
{
-"@odata.context": "$metadata#Sales(Customer(Country),
+ "@context": "$metadata#Sales(Customer(Country),
Product(Category(Name)),Total)",
"value": [
{ "Customer": { "Country": "USA", "Name": "Joe" },
"Product": { "Category": { "Name": "Non-Food" }, "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 1 },
+ "Total@type": "Decimal", "Total": 1 },
...
plus additional fifteen rollup entities for subtotals: five without
customer name
{ "Customer": { "Country": "USA" },
"Product": { "Category": { "Name": "Food" }, "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 2 },
+ "Total@type": "Decimal", "Total": 2 },
...
six without product name
{ "Customer": { "Country": "USA", "Name": "Joe" },
"Product": { "Category": { "Name": "Food" } },
- "Total@odata.type": "Decimal", "Total": 6 },
+ "Total@type": "Decimal", "Total": 6 },
...
and four with neither customer nor product name
{ "Customer": { "Country": "USA" },
"Product": { "Category": { "Name": "Food" } },
- "Total@odata.type": "Decimal", "Total": 14 },
+ "Total@type": "Decimal", "Total": 14 },
...
]
}
@@ -2974,7 +2974,7 @@ 3.2.1.2
results in
{
-"@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 1, "Amount": 1 },
{ "ID": 7, "Amount": 1 }
@@ -2987,7 +2987,7 @@ 3.2.1.2
results in
{
-"@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 3, "Amount": 4 },
{ "ID": 4, "Amount": 8 }
@@ -3017,7 +3017,7 @@ 3.2.1.2
results in
{
-"@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 1, "Amount": 1 },
{ "ID": 2, "Amount": 2 },
@@ -3034,7 +3034,7 @@ 3.2.1.2
results in
{
-"@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 3, "Amount": 4 },
{ "ID": 4, "Amount": 8 }
@@ -3058,7 +3058,7 @@ 3.2.1.2
results in
{
-"@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 1, "Amount": 1 },
{ "ID": 2, "Amount": 2 },
@@ -3074,7 +3074,7 @@ 3.2.1.2
results in
{
-"@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 3, "Amount": 4 },
{ "ID": 4, "Amount": 8 },
@@ -3097,7 +3097,7 @@ 3.2.1.2
results in
{
-"@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 3, "Amount": 4 },
{ "ID": 4, "Amount": 8 },
@@ -3137,14 +3137,14 @@ 3.2.1.2
results in
{
-"@odata.context": "$metadata#Sales(Product(Name),Total)",
+ "@context": "$metadata#Sales(Product(Name),Total)",
"value": [
{ "Product": { "Name": "Coffee" },
- "Total@odata.type": "Decimal", "Total": 12 },
+ "Total@type": "Decimal", "Total": 12 },
{ "Product": { "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 8 },
+ "Total@type": "Decimal", "Total": 8 },
{ "Product": { "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 4 }
+ "Total@type": "Decimal", "Total": 4 }
]
}
@@ -3165,7 +3165,7 @@ 3.2.1.2
results in
{
-"@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 3, "Amount": 4 },
{ "ID": 4, "Amount": 8 }
@@ -3192,7 +3192,7 @@ 3.2.1.2
results in
{
-"@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 6, "Amount": 2 },
{ "ID": 7, "Amount": 1 }
@@ -3223,7 +3223,7 @@ 3.2.1.2
results in
{
-"@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 4, "Amount": 8 },
{ "ID": 5, "Amount": 4 }
@@ -3276,16 +3276,16 @@ 3.2.1.2
results in
{
-"@odata.context": "$metadata#Sales(*,Tax)",
+ "@context": "$metadata#Sales(*,Tax)",
"value": [
- { "ID": 1, "Amount": 1, "Tax@odata.type": "Decimal", "Tax": 0.14 },
- { "ID": 2, "Amount": 2, "Tax@odata.type": "Decimal", "Tax": 0.12 },
- { "ID": 3, "Amount": 4, "Tax@odata.type": "Decimal", "Tax": 0.24 },
- { "ID": 4, "Amount": 8, "Tax@odata.type": "Decimal", "Tax": 0.48 },
- { "ID": 5, "Amount": 4, "Tax@odata.type": "Decimal", "Tax": 0.56 },
- { "ID": 6, "Amount": 2, "Tax@odata.type": "Decimal", "Tax": 0.12 },
- { "ID": 7, "Amount": 1, "Tax@odata.type": "Decimal", "Tax": 0.14 },
- { "ID": 8, "Amount": 2, "Tax@odata.type": "Decimal", "Tax": 0.28 }
+ { "ID": 1, "Amount": 1, "Tax@type": "Decimal", "Tax": 0.14 },
+ { "ID": 2, "Amount": 2, "Tax@type": "Decimal", "Tax": 0.12 },
+ { "ID": 3, "Amount": 4, "Tax@type": "Decimal", "Tax": 0.24 },
+ { "ID": 4, "Amount": 8, "Tax@type": "Decimal", "Tax": 0.48 },
+ { "ID": 5, "Amount": 4, "Tax@type": "Decimal", "Tax": 0.56 },
+ { "ID": 6, "Amount": 2, "Tax@type": "Decimal", "Tax": 0.12 },
+ { "ID": 7, "Amount": 1, "Tax@type": "Decimal", "Tax": 0.14 },
+ { "ID": 8, "Amount": 2, "Tax@type": "Decimal", "Tax": 0.28 }
]
}
@@ -3340,39 +3340,39 @@ 3.2.1.2
results in
{
-"@odata.context": "$metadata#Products(ID,Sale())",
+ "@context": "$metadata#Products(ID,Sale())",
"value": [
{ "ID": "P1",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 2, "Amount": 2 } },
{ "ID": "P1",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 6, "Amount": 2 } },
{ "ID": "P2",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 3, "Amount": 4 } },
{ "ID": "P2",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 4, "Amount": 8 } },
{ "ID": "P3",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 1, "Amount": 1 } },
{ "ID": "P3",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 5, "Amount": 4 } },
{ "ID": "P3",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 7, "Amount": 1 } },
{ "ID": "P3",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 8, "Amount": 2 } }
]
}
@@ -3383,7 +3383,7 @@ 3.2.1.2
complex property of type SalesModel.SalesComplexType
, the
complex property Sale
would be in the result regardless,
and its context would be
-"@odata.context": "#SalesModel.SalesComplexType"
.
+"@context": "#SalesModel.SalesComplexType"
.
Applying outerjoin
instead would return an additional
instance for product with "ID": "P4"
and Sale
having a null value.
@@ -3410,9 +3410,9 @@ 3.2.1.2
results in
{
-"@odata.context":"$metadata#Sales(Customers())",
+ "@context":"$metadata#Sales(Customers())",
"value": [
- { "Customers@odata.context": "#Sales(Customer(ID))",
+ { "Customers@context": "#Sales(Customer(ID))",
"Customers": [ { "Customer": { "ID": "C1" } },
{ "Customer": { "ID": "C2" } },
{ "Customer": { "ID": "C3" } } ] }
@@ -3490,26 +3490,26 @@ 3.2.1.2
results in
{
-"@odata.context": "$metadata#Customers(FilteredSales())",
+ "@context": "$metadata#Customers(FilteredSales())",
"value": [
{ "ID": "C1", "Name": "Joe", "Country": "USA",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": [{ "ID": "3", "Amount": 4 }]},
{ "ID": "C2", "Name": "Sue", "Country": "USA",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": [{ "ID": "4", "Amount": 8 },
{ "ID": "5", "Amount": 4 }]},
{ "ID": "C3", "Name": "Sue", "Country": "Netherlands",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": []},
{ "ID": "C4", "Name": "Luc", "Country": "France",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": []}
]
}
If Sales
was a collection-valued complex property of
type SalesModel.SalesComplexType
, the context would be
-"FilteredSales@odata.context": "#Collection(SalesModel.SalesComplexType)"
.
+"FilteredSales@context": "#Collection(SalesModel.SalesComplexType)"
.
3.5
@@ -3566,7 +3566,7 @@ 3.2.1.2
results in
{
-"@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": "4", "Amount": 8 }
]
@@ -3587,7 +3587,7 @@ 3.2.1.2
Both examples result in
{
-"@odata.context": "$metadata#Products",
+ "@context": "$metadata#Products",
"value": [
{ "ID": "P3", "Name": "Paper", "Color": "White", "TaxRate": 0.14 }
]
@@ -3609,7 +3609,7 @@ 3.2.1.2
the total amount.)
{
-"@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 3, "Amount": 4 },
{ "ID": 4, "Amount": 8 }
@@ -3647,7 +3647,7 @@ 3.2.1.2
results in
{
-"@odata.context": "$metadata#Sales(Total)",
+ "@context": "$metadata#Sales(Total)",
"value": []
}
@@ -3669,16 +3669,16 @@ 3.2.1.2
results in
{
-"@odata.context":"$metadata#Products(Sales(Total))",
+ "@context":"$metadata#Products(Sales(Total))",
"value": [
{ "ID": "P2", "Name": "Coffee", "Color": "Brown", "TaxRate": 0.06,
- "Sales": [ { "Total@odata.type": "Decimal", "Total": 12 } ] },
+ "Sales": [ { "Total@type": "Decimal", "Total": 12 } ] },
{ "ID": "P3", "Name": "Paper", "Color": "White", "TaxRate": 0.14,
- "Sales": [ { "Total@odata.type": "Decimal", "Total": 8 } ] },
+ "Sales": [ { "Total@type": "Decimal", "Total": 8 } ] },
{ "ID": "P4", "Name": "Pencil", "Color": "Black", "TaxRate": 0.14,
"Sales": [ { "Total": null } ] },
{ "ID": "P1", "Name": "Sugar", "Color": "White", "TaxRate": 0.06,
- "Sales": [ { "Total@odata.type": "Decimal", "Total": 4 } ] }
+ "Sales": [ { "Total@type": "Decimal", "Total": 4 } ] }
]
}
@@ -3722,7 +3722,7 @@ 3.2.1.2
results in
{
-"@odata.context": "$metadata#Collection(Edm.ComplexType)",
+ "@context": "$metadata#Collection(Edm.ComplexType)",
"value": [
{ "Products": { "Name": "Paper" }, "Sales": { "Amount": 1 } },
{ "Products": { "Name": "Sugar" }, "Sales": { "Amount": 2 } },
@@ -3741,17 +3741,17 @@ 3.2.1.2
results in
{
-"@odata.context": "$metadata#Collection(Edm.ComplexType)",
+ "@context": "$metadata#Collection(Edm.ComplexType)",
"value": [
{ "Products": { "Name": "Coffee" },
- "AggregatedSales@odata.context": "#Sales(Total)",
- "AggregatedSales": { "Total@odata.type": "Decimal", "Total": 12 } },
+ "AggregatedSales@context": "#Sales(Total)",
+ "AggregatedSales": { "Total@type": "Decimal", "Total": 12 } },
{ "Products": { "Name": "Paper" },
- "AggregatedSales@odata.context": "#Sales(Total)",
- "AggregatedSales": { "Total@odata.type": "Decimal", "Total": 8 } },
+ "AggregatedSales@context": "#Sales(Total)",
+ "AggregatedSales": { "Total@type": "Decimal", "Total": 8 } },
{ "Products": { "Name": "Sugar" },
- "AggregatedSales@odata.context": "#Sales(Total)",
- "AggregatedSales": { "Total@odata.type": "Decimal", "Total": 4 } }
+ "AggregatedSales@context": "#Sales(Total)",
+ "AggregatedSales": { "Total@type": "Decimal", "Total": 4 } }
]
}
@@ -4154,7 +4154,7 @@ 5.5
results in
{
-"@odata.context": "$metadata#SalesOrganizations",
+ "@context": "$metadata#SalesOrganizations",
"value": [
{ "ID": "EMEA Central", "Name": "EMEA Central" },
{ "ID": "Sales Netherlands", "Name": "Sales Netherlands" },
@@ -4178,7 +4178,7 @@ 5.5
results in
{
-"@odata.context": "$metadata#SalesOrganizations",
+ "@context": "$metadata#SalesOrganizations",
"value": [
{ "ID": "EMEA Central", "Name": "EMEA Central" },
{ "ID": "EMEA South", "Name": "EMEA South" },
@@ -4196,7 +4196,7 @@ 5.5
results in
{
-"@odata.context": "$metadata#SalesOrganizations",
+ "@context": "$metadata#SalesOrganizations",
"value": [
{ "ID": "Sales Office London", "Name": "Sales Office London" },
{ "ID": "Sales Office New York", "Name": "Sales Office New York" },
@@ -4215,7 +4215,7 @@ 5.5
results in
{
-"@odata.context": "$metadata#SalesOrganizations(*,Superordinate(ID))",
+ "@context": "$metadata#SalesOrganizations(*,Superordinate(ID))",
"value": [
{ "ID": "Sales Office London", "Name": "Sales Office London",
"Superordinate": { "ID": "EMEA United Kingdom" } },
@@ -4237,7 +4237,7 @@ 5.5
results in
{
-"@odata.context": "$metadata#Sales(ID)",
+ "@context": "$metadata#Sales(ID)",
"value": [
{ "ID": 6 },
{ "ID": 7 },
@@ -4470,12 +4470,12 @@ 5.5
results in
{
-"@odata.context": "$metadata#SalesOrganizations",
+ "@context": "$metadata#SalesOrganizations",
"value": [
{ "ID": "EMEA", "Name": "EMEA",
- "Superordinate": { "@odata.id": "SalesOrganizations('Sales')" } },
+ "Superordinate": { "@id": "SalesOrganizations('Sales')" } },
{ "ID": "US", "Name": "US",
- "Superordinate": { "@odata.id": "SalesOrganizations('Sales')" } },
+ "Superordinate": { "@id": "SalesOrganizations('Sales')" } },
{ "ID": "Sales", "Name": "Sales",
"Superordinate": null }
]
@@ -4493,14 +4493,14 @@ 5.5
results in
{
-"@odata.context": "$metadata#SalesOrganizations",
+ "@context": "$metadata#SalesOrganizations",
"value": [
{ "ID": "US West", "Name": "US West",
- "Superordinate": { "@odata.id": "SalesOrganizations('US')" } },
+ "Superordinate": { "@id": "SalesOrganizations('US')" } },
{ "ID": "US", "Name": "US",
- "Superordinate": { "@odata.id": "SalesOrganizations('Sales')" } },
+ "Superordinate": { "@id": "SalesOrganizations('Sales')" } },
{ "ID": "US East", "Name": "US East",
- "Superordinate": { "@odata.id": "SalesOrganizations('US')" } }
+ "Superordinate": { "@id": "SalesOrganizations('US')" } }
]
}
@@ -4517,7 +4517,7 @@ 5.5
results in
{
-"@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": "4", "Amount": 8,
"SalesOrganization": { "ID": "US East", "Name": "US East" } },
@@ -4737,12 +4737,12 @@ 5.5
results in
{
-"@odata.context": "$metadata#SalesOrganizations",
+ "@context": "$metadata#SalesOrganizations",
"value": [
{ "ID": "US", "Name": "US",
- "Superordinate": { "@odata.id": "SalesOrganizations('Sales')" } },
+ "Superordinate": { "@id": "SalesOrganizations('Sales')" } },
{ "ID": "US East", "Name": "US East",
- "Superordinate": { "@odata.id": "SalesOrganizations('US')" } }
+ "Superordinate": { "@id": "SalesOrganizations('US')" } }
]
}
@@ -4944,7 +4944,7 @@ 5.5
results in
{
-"@odata.context":
+ "@context":
"$metadata#SalesOrganizations(ID,Name,SubOrgCnt,Superordinate(ID))",
"value": [
{ "ID": "US West", "Name": "US West",
@@ -5006,18 +5006,18 @@ 5.5
results in
{
-"@odata.context": "$metadata#Sales(SalesOrganization(),
+ "@context": "$metadata#Sales(SalesOrganization(),
TotalAmountIncl,TotalAmountExcl)",
"value": [
{ "SalesOrganization": { "ID": "US West", "Name": "US West" },
- "TotalAmountIncl@odata.type": "Decimal", "TotalAmountIncl": 7,
- "TotalAmountExcl@odata.type": "Decimal" ,"TotalAmountExcl": 7 },
+ "TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 7,
+ "TotalAmountExcl@type": "Decimal" ,"TotalAmountExcl": 7 },
{ "SalesOrganization": { "ID": "US", "Name": "US" },
- "TotalAmountIncl@odata.type": "Decimal", "TotalAmountIncl": 19,
+ "TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 19,
"TotalAmountExcl": null },
{ "SalesOrganization": { "ID": "US East", "Name": "US East" },
- "TotalAmountIncl@odata.type": "Decimal", "TotalAmountIncl": 12,
- "TotalAmountExcl@odata.type": "Decimal", "TotalAmountExcl": 12 }
+ "TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 12,
+ "TotalAmountExcl@type": "Decimal", "TotalAmountExcl": 12 }
]
}
@@ -5038,7 +5038,7 @@ 5.5
results in
{
-"@odata.context": "$metadata#Sales(SalesOrganization(),TotalAmount)",
+ "@context": "$metadata#Sales(SalesOrganization(),TotalAmount)",
"value": [
{ "SalesOrganization": { "ID": "Sales", "Name": "Corporate Sales" },
"TotalAmount": null },
@@ -5093,7 +5093,7 @@ 7
results in
{
-"@odata.context": "$metadata#Customers(Name)",
+ "@context": "$metadata#Customers(Name)",
"value": [
{ "Name": "Luc" },
{ "Name": "Joe" },
@@ -5110,7 +5110,7 @@ 7
results in
{
-"@odata.context": "$metadata#Sales(Customer(Name))",
+ "@context": "$metadata#Sales(Customer(Name))",
"value": [
{ "Customer": { "Name": "Joe" } },
{ "Customer": { "Name": "Sue" } }
@@ -5134,7 +5134,7 @@ 7
results in
{
-"@odata.context": "$metadata#Sales(Customer(Name,ID))",
+ "@context": "$metadata#Sales(Customer(Name,ID))",
"value": [
{ "Customer": { "Name": "Joe", "ID": "C1" } },
{ "Customer": { "Name": "Sue", "ID": "C2" } },
@@ -5153,7 +5153,7 @@ 7
results in
{
-"@odata.context": "$metadata#Sales(Customer())",
+ "@context": "$metadata#Sales(Customer())",
"value": [
{ "Customer": { "ID": "C1", "Name": "Joe", "Country": "USA" } },
{ "Customer": { "ID": "C2", "Name": "Sue", "Country": "USA" } },
@@ -5169,7 +5169,7 @@ 7
and results in
{
-"@odata.context": "$metadata#Sales(Customer(Name,ID),Product(Name))",
+ "@context": "$metadata#Sales(Customer(Name,ID),Product(Name))",
"value": [
{ "Customer": { "Name": "Joe", "ID": "C1" },
"Product": { "Name": "Coffee"} },
@@ -5196,13 +5196,13 @@ 7
results in
{
-"@odata.context": "$metadata#Products(SalesModel.FoodProduct/Rating,
+ "@context": "$metadata#Products(SalesModel.FoodProduct/Rating,
SalesModel.NonFoodProduct/RatingClass)",
"value": [
- { "@odata.type": "#SalesModel.FoodProduct", "Rating": 5 },
- { "@odata.type": "#SalesModel.FoodProduct", "Rating": null },
- { "@odata.type": "#SalesModel.NonFoodProduct", "RatingClass": "average" },
- { "@odata.type": "#SalesModel.NonFoodProduct", "RatingClass": null }
+ { "@type": "#SalesModel.FoodProduct", "Rating": 5 },
+ { "@type": "#SalesModel.FoodProduct", "Rating": null },
+ { "@type": "#SalesModel.NonFoodProduct", "RatingClass": "average" },
+ { "@type": "#SalesModel.NonFoodProduct", "RatingClass": null }
]
}
@@ -5215,10 +5215,10 @@ 7
SalesModel.NonFoodProduct
s:
{
-"@odata.context": "$metadata#Products(@Core.AnyStructure)",
+ "@context": "$metadata#Products(@Core.AnyStructure)",
"value": [
- { "@odata.type": "#SalesModel.FoodProduct", "Rating": 5 },
- { "@odata.type": "#SalesModel.FoodProduct", "Rating": null },
+ { "@type": "#SalesModel.FoodProduct", "Rating": 5 },
+ { "@type": "#SalesModel.FoodProduct", "Rating": null },
{ }
]
}
@@ -5245,12 +5245,12 @@ 7
results in
{
-"@odata.context": "$metadata#Products(Name,Total)",
+ "@context": "$metadata#Products(Name,Total)",
"value": [
- { "Name": "Coffee", "Total@odata.type": "Decimal", "Total": 12 },
- { "Name": "Paper", "Total@odata.type": "Decimal", "Total": 8 },
+ { "Name": "Coffee", "Total@type": "Decimal", "Total": 12 },
+ { "Name": "Paper", "Total@type": "Decimal", "Total": 8 },
{ "Name": "Pencil", "Total": null },
- { "Name": "Sugar", "Total@odata.type": "Decimal", "Total": 4 }
+ { "Name": "Sugar", "Total@type": "Decimal", "Total": 4 }
]
}
Note that the base set of the request is Products
, so
@@ -5271,20 +5271,20 @@
7
results in
{
-"@odata.context": "$metadata#Products(AggregatedSales())",
+ "@context": "$metadata#Products(AggregatedSales())",
"value": [
{ "ID": "P2", "Name": "Coffee", "Color": "Brown", "TaxRate": 0.06,
- "AggregatedSales@odata.context": "#Sales(Total)",
- "AggregatedSales": [ { "Total@odata.type": "Decimal", "Total": 12 } ] },
+ "AggregatedSales@context": "#Sales(Total)",
+ "AggregatedSales": [ { "Total@type": "Decimal", "Total": 12 } ] },
{ "ID": "P3", "Name": "Paper", "Color": "White", "TaxRate": 0.14,
- "AggregatedSales@odata.context": "#Sales(Total)",
- "AggregatedSales": [ { "Total@odata.type": "Decimal", "Total": 8 } ] },
+ "AggregatedSales@context": "#Sales(Total)",
+ "AggregatedSales": [ { "Total@type": "Decimal", "Total": 8 } ] },
{ "ID": "P4", "Name": "Pencil", "Color": "Black", "TaxRate": 0.14,
- "AggregatedSales@odata.context": "#Sales(Total)",
+ "AggregatedSales@context": "#Sales(Total)",
"AggregatedSales": [ { "Total": null } ] },
{ "ID": "P1", "Name": "Sugar", "Color": "White", "TaxRate": 0.06,
- "AggregatedSales@odata.context": "#Sales(Total)",
- "AggregatedSales": [ { "Total@odata.type": "Decimal", "Total": 4 } ] }
+ "AggregatedSales@context": "#Sales(Total)",
+ "AggregatedSales": [ { "Total@type": "Decimal", "Total": 4 } ] }
]
}
@@ -5296,16 +5296,16 @@ 7
results in
{
-"@odata.context": "$metadata#Products(*,Total)",
+ "@context": "$metadata#Products(*,Total)",
"value": [
{ "ID": "P2", "Name": "Coffee", "Color": "Brown", "TaxRate": 0.06,
- "Total@odata.type": "Decimal", "Total": 12 },
+ "Total@type": "Decimal", "Total": 12 },
{ "ID": "P3", "Name": "Paper", "Color": "White", "TaxRate": 0.14,
- "Total@odata.type": "Decimal", "Total": 8 },
+ "Total@type": "Decimal", "Total": 8 },
{ "ID": "P4", "Name": "Pencil", "Color": "Black", "TaxRate": 0.14,
"Total": null },
{ "ID": "P1", "Name": "Sugar", "Color": "White", "TaxRate": 0.06,
- "Total@odata.type": "Decimal", "Total": 4 }
+ "Total@type": "Decimal", "Total": 4 }
]
}
The expression $it/Sales
refers to the sales of the
@@ -5322,17 +5322,17 @@
7
results in
{
-"@odata.context": "$metadata#Products(Name,TotalSales())",
+ "@context": "$metadata#Products(Name,TotalSales())",
"value": [
{ "Name": "Coffee",
- "TotalSales@odata.context": "#Sales(Total)/$entity",
- "TotalSales": { "Total@odata.type": "Decimal", "Total": 12 } },
+ "TotalSales@context": "#Sales(Total)/$entity",
+ "TotalSales": { "Total@type": "Decimal", "Total": 12 } },
{ "Name": "Paper",
- "TotalSales@odata.context": "#Sales(Total)/$entity",
- "TotalSales": { "Total@odata.type": "Decimal", "Total": 8 } },
+ "TotalSales@context": "#Sales(Total)/$entity",
+ "TotalSales": { "Total@type": "Decimal", "Total": 8 } },
{ "Name": "Sugar",
- "TotalSales@odata.context": "#Sales(Total)/$entity",
- "TotalSales": { "Total@odata.type": "Decimal", "Total": 4 } }
+ "TotalSales@context": "#Sales(Total)/$entity",
+ "TotalSales": { "Total@type": "Decimal", "Total": 4 } }
]
}
Applying outerjoin
instead would return an additional
@@ -5346,7 +5346,7 @@
7
results in
{
-"@odata.context": "$metadata#Sales(Customer(Country),AverageAmount)",
+ "@context": "$metadata#Sales(Customer(Country),AverageAmount)",
"value": [
{ "Customer": { "Country": "Netherlands" },
"AverageAmount": 1.6666666666666667 },
@@ -5364,12 +5364,12 @@ 7
results in
{
-"@odata.context": "$metadata#Products(Name,SalesCount)",
+ "@context": "$metadata#Products(Name,SalesCount)",
"value": [
- { "Name": "Coffee", "SalesCount@odata.type": "Decimal", "SalesCount": 2 },
- { "Name": "Paper", "SalesCount@odata.type": "Decimal", "SalesCount": 4 },
- { "Name": "Pencil", "SalesCount@odata.type": "Decimal", "SalesCount": 0 },
- { "Name": "Sugar", "SalesCount@odata.type": "Decimal", "SalesCount": 2 }
+ { "Name": "Coffee", "SalesCount@type": "Decimal", "SalesCount": 2 },
+ { "Name": "Paper", "SalesCount@type": "Decimal", "SalesCount": 4 },
+ { "Name": "Pencil", "SalesCount@type": "Decimal", "SalesCount": 0 },
+ { "Name": "Sugar", "SalesCount@type": "Decimal", "SalesCount": 2 }
]
}
@@ -5387,23 +5387,23 @@ 7
results in
{
-"@odata.context": "$metadata#Products(Name,AggregatedSales())",
+ "@context": "$metadata#Products(Name,AggregatedSales())",
"value": [
{ "Name": "Coffee",
- "AggregatedSales@odata.context": "#Sales(SalesCount,TotalAmount)",
+ "AggregatedSales@context": "#Sales(SalesCount,TotalAmount)",
"AggregatedSales": [ { "SalesCount": 2,
- "TotalAmount@odata.type": "Decimal", "TotalAmount": 12 } ] },
+ "TotalAmount@type": "Decimal", "TotalAmount": 12 } ] },
{ "Name": "Paper",
- "AggregatedSales@odata.context": "#Sales(SalesCount,TotalAmount)",
+ "AggregatedSales@context": "#Sales(SalesCount,TotalAmount)",
"AggregatedSales": [ { "SalesCount": 4,
- "TotalAmount@odata.type": "Decimal", "TotalAmount": 8 } ] },
+ "TotalAmount@type": "Decimal", "TotalAmount": 8 } ] },
{ "Name": "Pencil",
- "AggregatedSales@odata.context": "#Sales(SalesCount,TotalAmount)",
+ "AggregatedSales@context": "#Sales(SalesCount,TotalAmount)",
"AggregatedSales": [ { "SalesCount": 0, "TotalAmount": null } ] },
{ "Name": "Sugar",
- "AggregatedSales@odata.context": "#Sales(SalesCount,TotalAmount)",
+ "AggregatedSales@context": "#Sales(SalesCount,TotalAmount)",
"AggregatedSales": [ { "SalesCount": 2,
- "TotalAmount@odata.type": "Decimal", "TotalAmount": 4 } ] }
+ "TotalAmount@type": "Decimal", "TotalAmount": 4 } ] }
]
}
@@ -5417,7 +5417,7 @@ 7
results in
{
-"@odata.context": "$metadata#Products",
+ "@context": "$metadata#Products",
"value": [
{ "ID": "P2", "Name": "Coffee", "Color": "Brown", "TaxRate": 0.06 },
{ "ID": "P3", "Name": "Paper", "Color": "White", "TaxRate": 0.14 }
@@ -5431,7 +5431,7 @@ 7
results in
{
-"@odata.context": "$metadata#Customers",
+ "@context": "$metadata#Customers",
"value": [
{ "ID": "C2", "Name": "Sue", "Country": "USA" },
{ "ID": "C1", "Name": "Joe", "Country": "USA" },
@@ -5448,23 +5448,23 @@ 7
results in
{
-"@odata.context": "$metadata#Sales(*,Contribution)",
+ "@context": "$metadata#Sales(*,Contribution)",
"value": [
- { "ID": 1, "Amount": 1, "Contribution@odata.type": "Decimal",
+ { "ID": 1, "Amount": 1, "Contribution@type": "Decimal",
"Contribution": 0.0416666666666667 },
- { "ID": 2, "Amount": 2, "Contribution@odata.type": "Decimal",
+ { "ID": 2, "Amount": 2, "Contribution@type": "Decimal",
"Contribution": 0.0833333333333333 },
- { "ID": 3, "Amount": 4, "Contribution@odata.type": "Decimal",
+ { "ID": 3, "Amount": 4, "Contribution@type": "Decimal",
"Contribution": 0.1666666666666667 },
- { "ID": 4, "Amount": 8, "Contribution@odata.type": "Decimal",
+ { "ID": 4, "Amount": 8, "Contribution@type": "Decimal",
"Contribution": 0.3333333333333333 },
- { "ID": 5, "Amount": 4, "Contribution@odata.type": "Decimal",
+ { "ID": 5, "Amount": 4, "Contribution@type": "Decimal",
"Contribution": 0.1666666666666667 },
- { "ID": 6, "Amount": 2, "Contribution@odata.type": "Decimal",
+ { "ID": 6, "Amount": 2, "Contribution@type": "Decimal",
"Contribution": 0.0833333333333333 },
- { "ID": 7, "Amount": 1, "Contribution@odata.type": "Decimal",
+ { "ID": 7, "Amount": 1, "Contribution@type": "Decimal",
"Contribution": 0.0416666666666667 },
- { "ID": 8, "Amount": 2, "Contribution@odata.type": "Decimal",
+ { "ID": 8, "Amount": 2, "Contribution@type": "Decimal",
"Contribution": 0.0833333333333333 }
]
}
@@ -5477,7 +5477,7 @@ 7
results in
{
-"@odata.context": "$metadata#Categories",
+ "@context": "$metadata#Categories",
"value": [
{ "ID": "PG1", "Name": "Food" }
]
@@ -5495,14 +5495,14 @@ 7
results in
{
-"@odata.context": "$metadata#Sales(Customer(),CustomerAmount,Contribution)",
+ "@context": "$metadata#Sales(Customer(),CustomerAmount,Contribution)",
"value": [
- { "Customer": { "@odata.id": "Customers('C1')" },
- "Contribution@odata.type": "Decimal", "Contribution": 0.2916667 },
- { "Customer": { "@odata.id": "Customers('C2')" },
- "Contribution@odata.type": "Decimal", "Contribution": 0.5 },
- { "Customer": { "@odata.id": "Customers('C3')" },
- "Contribution@odata.type": "Decimal", "Contribution": 0.2083333 }
+ { "Customer": { "@id": "Customers('C1')" },
+ "Contribution@type": "Decimal", "Contribution": 0.2916667 },
+ { "Customer": { "@id": "Customers('C2')" },
+ "Contribution@type": "Decimal", "Contribution": 0.5 },
+ { "Customer": { "@id": "Customers('C3')" },
+ "Contribution@type": "Decimal", "Contribution": 0.2083333 }
]
}
@@ -5544,18 +5544,18 @@ 7
results in
{
-"@odata.context": "$metadata#Customers(
+ "@context": "$metadata#Customers(
Addresses(AugmentedSalesOrganization())",
"value": [
{ "ID": "C1", "Name": "Joe", "Country": "US",
"Addresses": [
{ "Locality": "Seattle",
"AugmentedSalesOrganization":
- { "@odata.context": "#SalesOrganizations/$entity",
+ { "@context": "#SalesOrganizations/$entity",
"ID": "US West", "SalesRegion": "US" } },
{ "Locality": "DC",
"AugmentedSalesOrganization":
- { "@odata.context": "#SalesOrganizations/$entity",
+ { "@context": "#SalesOrganizations/$entity",
"ID": "US", "SalesRegion": "Corporate Sales" } },
]
}, ...
@@ -5572,28 +5572,28 @@ 7
results in
{
-"@odata.context": "$metadata#Categories(FilteredProducts()",
+ "@context": "$metadata#Categories(FilteredProducts()",
"value": [
{ "ID": "PG1", "Name": "Food",
- "FilteredProducts@odata.context": "#Products(FilteredSales())",
+ "FilteredProducts@context": "#Products(FilteredSales())",
"FilteredProducts": [
{ "ID": "P1", "Name": "Sugar", "Color": "White",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": [] },
{ "ID": "P2", "Name": "Coffee", "Color": "Brown",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": [ { "ID": 3, "Amount": 4 },
{ "ID": 4, "Amount": 8 } ] }
]
},
{ "ID": "PG2", "Name": "Non-Food",
- "FilteredProducts@odata.context": "#Products(FilteredSales())",
+ "FilteredProducts@context": "#Products(FilteredSales())",
"FilteredProducts": [
{ "ID": "P3", "Name": "Paper", "Color": "White",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": [ { "ID": 5, "Amount": 4 } ] },
{ "ID": "P4", "Name": "Pencil", "Color": "Black",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": [] }
]
}
@@ -5621,29 +5621,29 @@ 7
results in
{
-"@odata.context": "$metadata#Customers(GroupedSales())",
+ "@context": "$metadata#Customers(GroupedSales())",
"value": [
{ "ID": "C1", "Name": "Joe", "Country": "USA",
- "GroupedSales@odata.context": "#Sales(@Core.AnyStructure)",
+ "GroupedSales@context": "#Sales(@Core.AnyStructure)",
"GroupedSales": [
{ },
{ },
{ }
] },
{ "ID": "C2", "Name": "Sue", "Country": "USA",
- "GroupedSales@odata.context": "#Sales(@Core.AnyStructure)",
+ "GroupedSales@context": "#Sales(@Core.AnyStructure)",
"GroupedSales": [
{ },
{ }
] },
{ "ID": "C3", "Name": "Joe", "Country": "Netherlands",
- "GroupedSales@odata.context": "#Sales(@Core.AnyStructure)",
+ "GroupedSales@context": "#Sales(@Core.AnyStructure)",
"GroupedSales": [
{ },
{ }
] },
{ "ID": "C4", "Name": "Luc", "Country": "France",
- "GroupedSales@odata.context": "#Sales(@Core.AnyStructure)",
+ "GroupedSales@context": "#Sales(@Core.AnyStructure)",
"GroupedSales": [ ] }
]
}
@@ -5656,22 +5656,22 @@ 7
returns the different combinations of products sold per country:
{
-"@odata.context":"$metadata#Customers(Country,ProductSales())",
+ "@context":"$metadata#Customers(Country,ProductSales())",
"value": [
{ "Country": "Netherlands",
- "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
+ "ProductSales@context": "#Sales(Product(Name))/$entity",
"ProductSales": { "Product": { "Name": "Paper" } } },
{ "Country": "Netherlands",
- "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
+ "ProductSales@context": "#Sales(Product(Name))/$entity",
"ProductSales": { "Product": { "Name": "Sugar" } } },
{ "Country": "USA",
- "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
+ "ProductSales@context": "#Sales(Product(Name))/$entity",
"ProductSales": { "Product": { "Name": "Coffee" } } },
{ "Country": "USA",
- "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
+ "ProductSales@context": "#Sales(Product(Name))/$entity",
"ProductSales": { "Product": { "Name": "Paper" } } },
{ "Country": "USA",
- "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
+ "ProductSales@context": "#Sales(Product(Name))/$entity",
"ProductSales": { "Product": { "Name": "Sugar" } } },
{ "Country": "France", "ProductSales": null }
]
@@ -5691,14 +5691,14 @@ 7
results in
{
-"@odata.context": "$metadata#Sales(Customer(Country),Actual,Forecast)",
+ "@context": "$metadata#Sales(Customer(Country),Actual,Forecast)",
"value": [
{ "Customer": { "Country": "Netherlands" },
- "Actual@odata.type": "Decimal", "Actual": 5,
- "Forecast@odata.type": "Decimal", "Forecast": 4 },
+ "Actual@type": "Decimal", "Actual": 5,
+ "Forecast@type": "Decimal", "Forecast": 4 },
{ "Customer": { "Country": "USA" },
- "Actual@odata.type": "Decimal", "Actual": 19,
- "Forecast@odata.type": "Decimal", "Forecast": 21 }
+ "Actual@type": "Decimal", "Actual": 19,
+ "Forecast@type": "Decimal", "Forecast": 21 }
]
}
@@ -5714,7 +5714,7 @@ 7
results in
{
-"@odata.context": "$metadata#Sales(Customer(Country),Amount)",
+ "@context": "$metadata#Sales(Customer(Country),Amount)",
"value": [
{ "Customer": { "Country": "Netherlands" }, "Amount": 5 },
{ "Customer": { "Country": "USA" }, "Amount": 19 }
@@ -5770,14 +5770,14 @@ 7.4
results in
{
-"@odata.context": "$metadata#Sales(Customer(Country),Total,AvgAmt)",
+ "@context": "$metadata#Sales(Customer(Country),Total,AvgAmt)",
"value": [
{ "Customer": { "Country": "Netherlands" },
- "Total@odata.type": "Decimal", "Total": 5,
- "AvgAmt@odata.type": "Decimal", "AvgAmt": 1.6666667 },
+ "Total@type": "Decimal", "Total": 5,
+ "AvgAmt@type": "Decimal", "AvgAmt": 1.6666667 },
{ "Customer": { "Country": "USA" },
- "Total@odata.type": "Decimal", "Total": 19,
- "AvgAmt@odata.type": "Decimal", "AvgAmt": 3.8 }
+ "Total@type": "Decimal", "Total": 19,
+ "AvgAmt@type": "Decimal", "AvgAmt": 3.8 }
]
}
@@ -5793,22 +5793,22 @@ 7.4
results in
{
-"@odata.context": "$metadata#Products(Name,Total,AggregatedSales())",
+ "@context": "$metadata#Products(Name,Total,AggregatedSales())",
"value": [
{ "Name": "Coffee", "Total": 12,
- "AggregatedSales@odata.context": "#Sales(AvgAmt)",
- "AggregatedSales": [ { "AvgAmt@odata.type": "Decimal",
+ "AggregatedSales@context": "#Sales(AvgAmt)",
+ "AggregatedSales": [ { "AvgAmt@type": "Decimal",
"AvgAmt": 6 } ] },
{ "Name": "Paper", "Total": 8,
- "AggregatedSales@odata.context": "#Sales(AvgAmt)",
- "AggregatedSales": [ { "AvgAmt@odata.type": "Decimal",
+ "AggregatedSales@context": "#Sales(AvgAmt)",
+ "AggregatedSales": [ { "AvgAmt@type": "Decimal",
"AvgAmt": 2 } ] },
{ "Name": "Pencil", "Total": null,
- "AggregatedSales@odata.context": "#Sales(AvgAmt)",
+ "AggregatedSales@context": "#Sales(AvgAmt)",
"AggregatedSales": [ { "AvgAmt": null } ] },
{ "Name": "Sugar", "Total": 4,
- "AggregatedSales@odata.context": "#Sales(AvgAmt)",
- "AggregatedSales": [ { "AvgAmt@odata.type": "Decimal",
+ "AggregatedSales@context": "#Sales(AvgAmt)",
+ "AggregatedSales": [ { "AvgAmt@type": "Decimal",
"AvgAmt": 2 } ] }
]
}
@@ -5823,12 +5823,12 @@ 7.4
much money was made with deals of this amount
{
-"@odata.context": "$metadata#Sales(Amount,Total)",
+ "@context": "$metadata#Sales(Amount,Total)",
"value": [
- { "Amount": 1, "Total@odata.type": "Decimal", "Total": 2 },
- { "Amount": 2, "Total@odata.type": "Decimal", "Total": 6 },
- { "Amount": 4, "Total@odata.type": "Decimal", "Total": 8 },
- { "Amount": 8, "Total@odata.type": "Decimal", "Total": 8 }
+ { "Amount": 1, "Total@type": "Decimal", "Total": 2 },
+ { "Amount": 2, "Total@type": "Decimal", "Total": 6 },
+ { "Amount": 4, "Total@type": "Decimal", "Total": 8 },
+ { "Amount": 8, "Total@type": "Decimal", "Total": 8 }
]
}
@@ -5851,19 +5851,19 @@ 7.4
results in
{
-"@odata.context": "$metadata#Sales(Customer(Country),Total)",
+ "@context": "$metadata#Sales(Customer(Country),Total)",
"value": [
{ "Customer":{ "Country": "USA" }, "Product":{ "Name": "Coffee" },
- "Total@odata.type": "Decimal", "Total": 12
+ "Total@type": "Decimal", "Total": 12
},
{ "Customer":{ "Country": "Netherlands" }, "Product":{ "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 3
+ "Total@type": "Decimal", "Total": 3
},
{ "Customer":{ "Country": "USA" },
- "Total@odata.type": "Decimal", "Total": 19
+ "Total@type": "Decimal", "Total": 19
},
{ "Customer":{ "Country": "Netherlands" },
- "Total@odata.type": "Decimal", "Total": 5
+ "Total@type": "Decimal", "Total": 5
}
]
}
@@ -5877,22 +5877,22 @@ 7.4
results in
{
-"@odata.context": "$metadata#Sales(Customer(Country),Product(Name),Total)",
+ "@context": "$metadata#Sales(Customer(Country),Product(Name),Total)",
"value": [
{ "Customer":{ "Country": "Netherlands" }, "Product":{ "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 3
+ "Total@type": "Decimal", "Total": 3
},
{ "Customer":{ "Country": "Netherlands" }, "Product":{ "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 2
+ "Total@type": "Decimal", "Total": 2
},
{ "Customer":{ "Country": "USA" }, "Product":{ "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 2
+ "Total@type": "Decimal", "Total": 2
},
{ "Customer":{ "Country": "USA" }, "Product":{ "Name": "Coffee" },
- "Total@odata.type": "Decimal", "Total": 12
+ "Total@type": "Decimal", "Total": 12
},
{ "Customer":{ "Country": "USA" }, "Product":{ "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 5
+ "Total@type": "Decimal", "Total": 5
}
]
}
@@ -5912,7 +5912,7 @@ 7.4
arises.
{
-"@odata.context": "$metadata#Sales(*,per,Customer(ID),Product(ID))",
+ "@context": "$metadata#Sales(*,per,Customer(ID),Product(ID))",
"value": [
{ "Customer": { "ID": "C1" }, "Product": { "ID": "P2" },
"ID": "3", "Amount": 4, "per": "Customer" },
@@ -5961,18 +5961,18 @@ 7.4
results in
{
-"@odata.context": "$metadata#Sales(Customer(Country),Total)",
+ "@context": "$metadata#Sales(Customer(Country),Total)",
"value": [
{ "Customer": { "Country": "Netherlands" },
"Product": { "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 3 },
+ "Total@type": "Decimal", "Total": 3 },
{ "Customer": { "Country": "Netherlands" },
- "Total@odata.type": "Decimal", "Total": 2 },
+ "Total@type": "Decimal", "Total": 2 },
{ "Customer": { "Country": "USA" },
"Product": { "Name": "Coffee" },
- "Total@odata.type": "Decimal", "Total": 12 },
+ "Total@type": "Decimal", "Total": 12 },
{ "Customer": { "Country": "USA" },
- "Total@odata.type": "Decimal", "Total": 7 }
+ "Total@type": "Decimal", "Total": 7 }
]
}
Note that these two entities get their values for the Country
@@ -6016,24 +6016,24 @@
7.4
results in
{
-"@odata.context": "$metadata#Sales(CustomerCountryAverage)",
+ "@context": "$metadata#Sales(CustomerCountryAverage)",
"value": [
{ "Customer": { "Country": "USA", "ID": "C1" },
- "CustomerCountryAverage@odata.type":"Decimal",
+ "CustomerCountryAverage@type":"Decimal",
"CustomerCountryAverage": 7 },
{ "Customer": { "Country": "USA", "ID": "C2" },
- "CustomerCountryAverage@odata.type":"Decimal",
+ "CustomerCountryAverage@type":"Decimal",
"CustomerCountryAverage": 12 },
{ "Customer": { "Country": "USA" },
- "CustomerCountryAverage@odata.type":"Decimal",
+ "CustomerCountryAverage@type":"Decimal",
"CustomerCountryAverage": 9.5 },
{ "Customer": { "Country": "Netherlands", "ID": "C3" },
- "CustomerCountryAverage@odata.type":"Decimal",
+ "CustomerCountryAverage@type":"Decimal",
"CustomerCountryAverage": 5 },
{ "Customer": { "Country": "Netherlands" },
- "CustomerCountryAverage@odata.type":"Decimal",
+ "CustomerCountryAverage@type":"Decimal",
"CustomerCountryAverage": 5 },
- { "CustomerCountryAverage@odata.type":"Decimal",
+ { "CustomerCountryAverage@type":"Decimal",
"CustomerCountryAverage": 7.25 }
]
}
@@ -6062,17 +6062,17 @@ 7.4
results in
{
-"@odata.context": "$metadata#Sales(TotalAmount,SalesOrganization())",
+ "@context": "$metadata#Sales(TotalAmount,SalesOrganization())",
"value": [
- { "TotalAmount@odata.type": "Decimal", "TotalAmount": 19,
+ { "TotalAmount@type": "Decimal", "TotalAmount": 19,
"SalesOrganization": { "ID": "US", "Name": "US",
- "Superordinate": { "@odata.id": "SalesOrganizations('Sales')" } } },
- { "TotalAmount@odata.type": "Decimal", "TotalAmount": 12,
+ "Superordinate": { "@id": "SalesOrganizations('Sales')" } } },
+ { "TotalAmount@type": "Decimal", "TotalAmount": 12,
"SalesOrganization": { "ID": "US East", "Name": "US East",
- "Superordinate": { "@odata.id": "SalesOrganizations('US')" } } },
- { "TotalAmount@odata.type": "Decimal", "TotalAmount": 7,
+ "Superordinate": { "@id": "SalesOrganizations('US')" } } },
+ { "TotalAmount@type": "Decimal", "TotalAmount": 7,
"SalesOrganization": { "ID": "US West", "Name": "US West",
- "Superordinate": { "@odata.id": "SalesOrganizations('US')" } } }
+ "Superordinate": { "@id": "SalesOrganizations('US')" } } }
]
}
Note that this example returns the actual total sums regardless of
@@ -6095,24 +6095,24 @@
7.4
results in
{
-"@odata.context": "$metadata#Sales(PaperSalesCount,SalesOrganization())",
+ "@context": "$metadata#Sales(PaperSalesCount,SalesOrganization())",
"value": [
- { "PaperSalesCount@odata.type": "Decimal", "PaperSalesCount": 2,
+ { "PaperSalesCount@type": "Decimal", "PaperSalesCount": 2,
"SalesOrganization": { "ID": "US", "Name": "US",
- "Superordinate": { "@odata.id": "SalesOrganizations('Sales')" } } },
- { "PaperSalesCount@odata.type": "Decimal", "PaperSalesCount": 1,
+ "Superordinate": { "@id": "SalesOrganizations('Sales')" } } },
+ { "PaperSalesCount@type": "Decimal", "PaperSalesCount": 1,
"SalesOrganization": { "ID": "US East", "Name": "US East",
- "Superordinate": { "@odata.id": "SalesOrganizations('US')" } } },
- { "PaperSalesCount@odata.type": "Decimal", "PaperSalesCount": 1,
+ "Superordinate": { "@id": "SalesOrganizations('US')" } } },
+ { "PaperSalesCount@type": "Decimal", "PaperSalesCount": 1,
"SalesOrganization": { "ID": "US West", "Name": "US West",
- "Superordinate": { "@odata.id": "SalesOrganizations('US')" } } },
- { "PaperSalesCount@odata.type": "Decimal", "PaperSalesCount": 2,
+ "Superordinate": { "@id": "SalesOrganizations('US')" } } },
+ { "PaperSalesCount@type": "Decimal", "PaperSalesCount": 2,
"SalesOrganization": { "ID": "EMEA", "Name": "EMEA",
- "Superordinate": { "@odata.id": "SalesOrganizations('Sales')" } } },
- { "PaperSalesCount@odata.type": "Decimal", "PaperSalesCount": 2,
+ "Superordinate": { "@id": "SalesOrganizations('Sales')" } } },
+ { "PaperSalesCount@type": "Decimal", "PaperSalesCount": 2,
"SalesOrganization": { "ID": "EMEA Central", "Name": "EMEA Central",
- "Superordinate": { "@odata.id": "SalesOrganizations('EMEA')" } } },
- { "PaperSalesCount@odata.type": "Decimal", "PaperSalesCount": 4,
+ "Superordinate": { "@id": "SalesOrganizations('EMEA')" } } },
+ { "PaperSalesCount@type": "Decimal", "PaperSalesCount": 4,
"SalesOrganization": { "ID": "Sales", "Name": "Sales",
"Superordinate": null } }
]
@@ -6201,18 +6201,18 @@ 7.4
results in
{
-"@odata.context": "$metadata#Sales(SalesOrganization(ID),
+ "@context": "$metadata#Sales(SalesOrganization(ID),
TotalAmountIncl,TotalAmountExcl)",
"value": [
{ "SalesOrganization": { "ID": "US", "Name": "US" },
- "TotalAmountIncl@odata.type": "Decimal", "TotalAmountIncl": 19,
+ "TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 19,
"TotalAmountExcl": null },
{ "SalesOrganization": { "ID": "US East", "Name": "US East" },
- "TotalAmountIncl@odata.type": "Decimal", "TotalAmountIncl": 12,
- "TotalAmountExcl@odata.type": "Decimal", "TotalAmountExcl": 12 },
+ "TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 12,
+ "TotalAmountExcl@type": "Decimal", "TotalAmountExcl": 12 },
{ "SalesOrganization": { "ID": "US West", "Name": "US West" },
- "TotalAmountIncl@odata.type": "Decimal", "TotalAmountIncl": 7,
- "TotalAmountExcl@odata.type": "Decimal" ,"TotalAmountExcl": 7 }
+ "TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 7,
+ "TotalAmountExcl@type": "Decimal" ,"TotalAmountExcl": 7 }
]
}
@@ -6236,7 +6236,7 @@ 7.4
class="math inline">\(σ(x)={}\){"Sales": [{"SalesOrganization": {"ID": "US"}}]}
.
{
-"@odata.context":
+ "@context":
"$metadata#Products(ID,Sales(SalesOrganization(ID)))",
"value": [
{ "ID": "P1", "Sales": [ { "SalesOrganization": { "ID": "Sales" } } ] },
@@ -6272,7 +6272,7 @@ 7.4
results in
{
-"@odata.context": "$metadata#Products(Sales(SalesOrganization(ID)),
+ "@context": "$metadata#Products(Sales(SalesOrganization(ID)),
SoldProducts)",
"value": [
{ "Sales": [ { "SalesOrganization": { "ID": "Sales" } } ],
@@ -6346,17 +6346,17 @@ 7.4
results in
{
-"@odata.context": "$metadata#Sales(SalesOrganization(ID),TotalAmount)",
+ "@context": "$metadata#Sales(SalesOrganization(ID),TotalAmount)",
"value": [
{ "SalesOrganization": { "ID": "Sales", "ProductCategories": [ ] },
- "TotalAmount@odata.type": "Decimal", "TotalAmount": 24 },
+ "TotalAmount@type": "Decimal", "TotalAmount": 24 },
{ "SalesOrganization": { "ID": "US", "ProductCategories": [
- { "@odata.id": "ProductCategories('Food')" },
- { "@odata.id": "ProductCategories('Cereals')" } ] },
- "TotalAmount@odata.type": "Decimal", "TotalAmount": 19 },
+ { "@id": "ProductCategories('Food')" },
+ { "@id": "ProductCategories('Cereals')" } ] },
+ "TotalAmount@type": "Decimal", "TotalAmount": 19 },
{ "SalesOrganization": { "ID": "US West", "ProductCategories": [
- { "@odata.id": "ProductCategories('Organic cereals')" } ] },
- "TotalAmount@odata.type": "Decimal", "TotalAmount": 7 }
+ { "@id": "ProductCategories('Organic cereals')" } ] },
+ "TotalAmount@type": "Decimal", "TotalAmount": 7 }
]
}
traverse
acts here as a filter, hence
@@ -6392,9 +6392,9 @@
7.4
means "filter first, then aggregate", and results in
{
-"@odata.context": "$metadata#Sales(Total)",
+ "@context": "$metadata#Sales(Total)",
"value": [
- { "Total@odata.type": "Decimal", "Total": 2 }
+ { "Total@type": "Decimal", "Total": 2 }
]
}
@@ -6408,12 +6408,12 @@ 7.4
results in
{
-"@odata.context": "$metadata#Sales(Product(Name),Total)",
+ "@context": "$metadata#Sales(Product(Name),Total)",
"value": [
{ "Product": { "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 4 },
+ "Total@type": "Decimal", "Total": 4 },
{ "Product": { "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 4 }
+ "Total@type": "Decimal", "Total": 4 }
]
}
@@ -6438,13 +6438,13 @@ 7.4
results in
{
-"@odata.context": "$metadata#Cities(Continent(Name),Country(Name),
+ "@context": "$metadata#Cities(Continent(Name),Country(Name),
TotalPopulation)",
"value": [
{ "Continent": { "Name": "Asia" }, "Country": { "Name": "China" },
- "TotalPopulation@odata.type": "Int32", "TotalPopulation": 1412000000 },
+ "TotalPopulation@type": "Int32", "TotalPopulation": 1412000000 },
{ "Continent": { "Name": "Asia" }, "Country": { "Name": "India" },
- "TotalPopulation@odata.type": "Int32", "TotalPopulation": 1408000000 },
+ "TotalPopulation@type": "Int32", "TotalPopulation": 1408000000 },
...
]
}
@@ -6522,15 +6522,15 @@ 7.4
results in
{
-"@odata.context":"$metadata#Sales(Product(Category(ID)),Customers())",
+ "@context":"$metadata#Sales(Product(Category(ID)),Customers())",
"value": [
{ "Product": { "Category": { "ID": "PG1" } },
- "Customers@odata.context": "#Sales(Customer(ID))",
+ "Customers@context": "#Sales(Customer(ID))",
"Customers": [ { "Customer": { "ID": "C1" } },
{ "Customer": { "ID": "C2" } },
{ "Customer": { "ID": "C3" } } ] },
{ "Product": { "Category": { "ID": "PG2" } },
- "Customers@odata.context": "#Sales(Customer(ID))",
+ "Customers@context": "#Sales(Customer(ID))",
"Customers": [ { "Customer": { "ID": "C1" } },
{ "Customer": { "ID": "C2" } },
{ "Customer": { "ID": "C3" } } ] }
diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
index 016cd7e81..bed978ba7 100644
--- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
+++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
@@ -1143,10 +1143,10 @@ GET /service/Sales?$apply=aggregate(Amount with sum as Total,
results in
```json
{
- "@odata.context": "$metadata#Sales(Total, MxA)",
+ "@context": "$metadata#Sales(Total, MxA)",
"value": [
- { "Total@odata.type": "Decimal", "Total": 24,
- "MxA@odata.type": "Decimal", "MxA": 8 }
+ { "Total@type": "Decimal", "Total": 24,
+ "MxA@type": "Decimal", "MxA": 8 }
]
}
```
@@ -1161,9 +1161,9 @@ GET /service/Sales?$apply=aggregate(Amount mul Product/TaxRate
results in
```json
{
- "@odata.context": "$metadata#Sales(Tax)",
+ "@context": "$metadata#Sales(Tax)",
"value": [
- { "Tax@odata.type": "Decimal", "Tax": 2.08 }
+ { "Tax@type": "Decimal", "Tax": 2.08 }
]
}
```
@@ -1187,9 +1187,9 @@ GET /service/Sales?$apply=aggregate(Amount with sum as Total)
results in
```json
{
- "@odata.context": "$metadata#Sales(Total)",
+ "@context": "$metadata#Sales(Total)",
"value": [
- { "Total@odata.type": "Decimal", "Total": 24 }
+ { "Total@type": "Decimal", "Total": 24 }
]
}
```
@@ -1209,9 +1209,9 @@ GET /service/Sales?$apply=aggregate(Amount with min as MinAmount)
results in
```json
{
- "@odata.context": "$metadata#Sales(MinAmount)",
+ "@context": "$metadata#Sales(MinAmount)",
"value": [
- { "MinAmount@odata.type": "Decimal", "MinAmount": 1 }
+ { "MinAmount@type": "Decimal", "MinAmount": 1 }
]
}
```
@@ -1231,9 +1231,9 @@ GET /service/Sales?$apply=aggregate(Amount with max as MaxAmount)
results in
```json
{
- "@odata.context": "$metadata#Sales(MaxAmount)",
+ "@context": "$metadata#Sales(MaxAmount)",
"value": [
- { "MaxAmount@odata.type": "Decimal", "MaxAmount": 8 }
+ { "MaxAmount@type": "Decimal", "MaxAmount": 8 }
]
}
```
@@ -1253,9 +1253,9 @@ GET /service/Sales?$apply=aggregate(Amount with average as AverageAmount)
results in
```json
{
- "@odata.context": "$metadata#Sales(AverageAmount)",
+ "@context": "$metadata#Sales(AverageAmount)",
"value": [
- { "AverageAmount@odata.type": "Decimal", "AverageAmount": 3.0 }
+ { "AverageAmount@type": "Decimal", "AverageAmount": 3.0 }
]
}
```
@@ -1276,9 +1276,9 @@ GET /service/Sales?$apply=aggregate(Product with countdistinct
results in
```json
{
- "@odata.context": "$metadata#Sales(DistinctProducts)",
+ "@context": "$metadata#Sales(DistinctProducts)",
"value": [
- { "DistinctProducts@odata.type": "Decimal", "DistinctProducts": 3 }
+ { "DistinctProducts@type": "Decimal", "DistinctProducts": 3 }
]
}
```
@@ -1302,13 +1302,13 @@ GET /service/Sales?$apply=groupby((Customer/Country),
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Country),Total,ProductNames)",
+ "@context": "$metadata#Sales(Customer(Country),Total,ProductNames)",
"value": [
{ "Customer": { "Country": "Netherlands" },
- "Total@odata.type": "Decimal", "Total": 5,
+ "Total@type": "Decimal", "Total": 5,
"ProductNames": "Paper,Sugar" },
{ "Customer": { "Country": "USA" },
- "Total@odata.type": "Decimal", "Total": 19,
+ "Total@type": "Decimal", "Total": 19,
"ProductNames": "Coffee,Paper,Sugar" }
]
}
@@ -1329,9 +1329,9 @@ GET /service/Sales?$apply=aggregate($count as SalesCount)
results in
```json
{
- "@odata.context": "$metadata#Sales(SalesCount)",
+ "@context": "$metadata#Sales(SalesCount)",
"value": [
- { "SalesCount@odata.type": "Decimal", "SalesCount": 8 }
+ { "SalesCount@type": "Decimal", "SalesCount": 8 }
]
}
```
@@ -1368,9 +1368,9 @@ GET /service/Sales?$apply=groupby((Time),aggregate(Amount with sum as Total))
and results in the average sales volume per day
```json
{
- "@odata.context": "$metadata#Sales(DailyAverage)",
+ "@context": "$metadata#Sales(DailyAverage)",
"value": [
- { "DailyAverage@odata.type": "Decimal", "DailyAverage": 3.428571428571429 }
+ { "DailyAverage@type": "Decimal", "DailyAverage": 3.428571428571429 }
]
}
```
@@ -1404,7 +1404,7 @@ GET /service/Sales?$apply=concat(topcount(2,Amount),
results in
```json
{
- "@odata.context": "$metadata#Sales(Amount)",
+ "@context": "$metadata#Sales(Amount)",
"value": [
{ "ID": 4, "Amount": 8 },
{ "ID": 3, "Amount": 4 },
@@ -1462,23 +1462,23 @@ GET /service/Sales?$apply=groupby((Customer/Country,Product/Name),
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Country),Product(Name),Total)",
+ "@context": "$metadata#Sales(Customer(Country),Product(Name),Total)",
"value": [
{ "Customer": { "Country": "Netherlands" },
"Product": { "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 3 },
+ "Total@type": "Decimal", "Total": 3 },
{ "Customer": { "Country": "Netherlands" },
"Product": { "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 2 },
+ "Total@type": "Decimal", "Total": 2 },
{ "Customer": { "Country": "USA" },
"Product": { "Name": "Coffee" },
- "Total@odata.type": "Decimal", "Total": 12 },
+ "Total@type": "Decimal", "Total": 12 },
{ "Customer": { "Country": "USA" },
"Product": { "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 5 },
+ "Total@type": "Decimal", "Total": 5 },
{ "Customer": { "Country": "USA" },
"Product": { "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 2 }
+ "Total@type": "Decimal", "Total": 2 }
]
}
```
@@ -1494,7 +1494,7 @@ GET /service/Sales?$apply=groupby((Product/Name,Amount))
results in
```json
{
- "@odata.context": "$metadata#Sales(Product(Name),Amount)",
+ "@context": "$metadata#Sales(Product(Name),Amount)",
"value": [
{ "Product": { "Name": "Coffee" }, "Amount": 4 },
{ "Product": { "Name": "Coffee" }, "Amount": 8 },
@@ -1546,33 +1546,33 @@ GET /service/Sales?$apply=groupby((rollup(Customer/Country,Customer/Name),
results in seven entities for the finest grouping level
```json
{
- "@odata.context": "$metadata#Sales(Customer(Country),
+ "@context": "$metadata#Sales(Customer(Country),
Product(Category(Name)),Total)",
"value": [
{ "Customer": { "Country": "USA", "Name": "Joe" },
"Product": { "Category": { "Name": "Non-Food" }, "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 1 },
+ "Total@type": "Decimal", "Total": 1 },
...
```
plus additional fifteen rollup entities for subtotals: five without customer name
```json
{ "Customer": { "Country": "USA" },
"Product": { "Category": { "Name": "Food" }, "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 2 },
+ "Total@type": "Decimal", "Total": 2 },
...
```
six without product name
```json
{ "Customer": { "Country": "USA", "Name": "Joe" },
"Product": { "Category": { "Name": "Food" } },
- "Total@odata.type": "Decimal", "Total": 6 },
+ "Total@type": "Decimal", "Total": 6 },
...
```
and four with neither customer nor product name
```json
{ "Customer": { "Country": "USA" },
"Product": { "Category": { "Name": "Food" } },
- "Total@odata.type": "Decimal", "Total": 14 },
+ "Total@type": "Decimal", "Total": 14 },
...
]
}
@@ -1628,7 +1628,7 @@ GET /service/Sales?$apply=bottomcount(2,Amount)
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 1, "Amount": 1 },
{ "ID": 7, "Amount": 1 }
@@ -1645,7 +1645,7 @@ GET /service/Sales?$apply=topcount(2,Amount)
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 3, "Amount": 4 },
{ "ID": 4, "Amount": 8 }
@@ -1667,7 +1667,7 @@ GET /service/Sales?$apply=bottompercent(50,Amount)
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 1, "Amount": 1 },
{ "ID": 2, "Amount": 2 },
@@ -1688,7 +1688,7 @@ GET /service/Sales?$apply=toppercent(50,Amount)
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 3, "Amount": 4 },
{ "ID": 4, "Amount": 8 }
@@ -1709,7 +1709,7 @@ GET /service/Sales?$apply=bottomsum(7,Amount)
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 1, "Amount": 1 },
{ "ID": 2, "Amount": 2 },
@@ -1729,7 +1729,7 @@ GET /service/Sales?$apply=topsum(15,Amount)
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 3, "Amount": 4 },
{ "ID": 4, "Amount": 8 },
@@ -1751,7 +1751,7 @@ GET /service/Sales?$apply=filter(Amount gt 3)
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 3, "Amount": 4 },
{ "ID": 4, "Amount": 8 },
@@ -1786,14 +1786,14 @@ GET /service/Sales?$apply=groupby((Product/Name),
results in
```json
{
- "@odata.context": "$metadata#Sales(Product(Name),Total)",
+ "@context": "$metadata#Sales(Product(Name),Total)",
"value": [
{ "Product": { "Name": "Coffee" },
- "Total@odata.type": "Decimal", "Total": 12 },
+ "Total@type": "Decimal", "Total": 12 },
{ "Product": { "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 8 },
+ "Total@type": "Decimal", "Total": 8 },
{ "Product": { "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 4 }
+ "Total@type": "Decimal", "Total": 4 }
]
}
```
@@ -1811,7 +1811,7 @@ GET /service/Sales?$apply=search(coffee)
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 3, "Amount": 4 },
{ "ID": 4, "Amount": 8 }
@@ -1834,7 +1834,7 @@ GET /service/Sales?$apply=orderby(Customer/Name desc)/skip(2)/top(2)
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 6, "Amount": 2 },
{ "ID": 7, "Amount": 1 }
@@ -1859,7 +1859,7 @@ GET /service/Sales?$apply=orderby(Customer/Name desc)/top(2)
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 4, "Amount": 8 },
{ "ID": 5, "Amount": 4 }
@@ -1894,16 +1894,16 @@ GET /service/Sales?$apply=compute(Amount mul Product/TaxRate as Tax)
results in
```json
{
- "@odata.context": "$metadata#Sales(*,Tax)",
+ "@context": "$metadata#Sales(*,Tax)",
"value": [
- { "ID": 1, "Amount": 1, "Tax@odata.type": "Decimal", "Tax": 0.14 },
- { "ID": 2, "Amount": 2, "Tax@odata.type": "Decimal", "Tax": 0.12 },
- { "ID": 3, "Amount": 4, "Tax@odata.type": "Decimal", "Tax": 0.24 },
- { "ID": 4, "Amount": 8, "Tax@odata.type": "Decimal", "Tax": 0.48 },
- { "ID": 5, "Amount": 4, "Tax@odata.type": "Decimal", "Tax": 0.56 },
- { "ID": 6, "Amount": 2, "Tax@odata.type": "Decimal", "Tax": 0.12 },
- { "ID": 7, "Amount": 1, "Tax@odata.type": "Decimal", "Tax": 0.14 },
- { "ID": 8, "Amount": 2, "Tax@odata.type": "Decimal", "Tax": 0.28 }
+ { "ID": 1, "Amount": 1, "Tax@type": "Decimal", "Tax": 0.14 },
+ { "ID": 2, "Amount": 2, "Tax@type": "Decimal", "Tax": 0.12 },
+ { "ID": 3, "Amount": 4, "Tax@type": "Decimal", "Tax": 0.24 },
+ { "ID": 4, "Amount": 8, "Tax@type": "Decimal", "Tax": 0.48 },
+ { "ID": 5, "Amount": 4, "Tax@type": "Decimal", "Tax": 0.56 },
+ { "ID": 6, "Amount": 2, "Tax@type": "Decimal", "Tax": 0.12 },
+ { "ID": 7, "Amount": 1, "Tax@type": "Decimal", "Tax": 0.14 },
+ { "ID": 8, "Amount": 2, "Tax@type": "Decimal", "Tax": 0.28 }
]
}
```
@@ -1931,45 +1931,45 @@ GET /service/Products?$apply=join(Sales as Sale)&$select=ID&$expand=Sale
results in
```json
{
- "@odata.context": "$metadata#Products(ID,Sale())",
+ "@context": "$metadata#Products(ID,Sale())",
"value": [
{ "ID": "P1",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 2, "Amount": 2 } },
{ "ID": "P1",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 6, "Amount": 2 } },
{ "ID": "P2",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 3, "Amount": 4 } },
{ "ID": "P2",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 4, "Amount": 8 } },
{ "ID": "P3",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 1, "Amount": 1 } },
{ "ID": "P3",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 5, "Amount": 4 } },
{ "ID": "P3",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 7, "Amount": 1 } },
{ "ID": "P3",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 8, "Amount": 2 } }
]
}
```
-In this example, `$expand=Sale` is used to include the target entities in the result. There are no subsequent transformations like `groupby` that would cause it to be expanded by default. If the first parameter `Sales` was a collection-valued complex property of type `SalesModel.SalesComplexType`, the complex property `Sale` would be in the result regardless, and its context would be `"@odata.context": "#SalesModel.SalesComplexType"`.
+In this example, `$expand=Sale` is used to include the target entities in the result. There are no subsequent transformations like `groupby` that would cause it to be expanded by default. If the first parameter `Sales` was a collection-valued complex property of type `SalesModel.SalesComplexType`, the complex property `Sale` would be in the result regardless, and its context would be `"@context": "#SalesModel.SalesComplexType"`.
Applying `outerjoin` instead would return an additional instance for product with `"ID": "P4"` and `Sale` having a null value.
:::
@@ -1988,9 +1988,9 @@ GET /service/Sales?$apply=nest(groupby((Customer/ID)) as Customers))
results in
```json
{
- "@odata.context":"$metadata#Sales(Customers())",
+ "@context":"$metadata#Sales(Customers())",
"value": [
- { "Customers@odata.context": "#Sales(Customer(ID))",
+ { "Customers@context": "#Sales(Customer(ID))",
"Customers": [ { "Customer": { "ID": "C1" } },
{ "Customer": { "ID": "C2" } },
{ "Customer": { "ID": "C3" } } ] }
@@ -2025,26 +2025,26 @@ GET /service/Customers?$apply=addnested(Sales,
results in
```json
{
- "@odata.context": "$metadata#Customers(FilteredSales())",
+ "@context": "$metadata#Customers(FilteredSales())",
"value": [
{ "ID": "C1", "Name": "Joe", "Country": "USA",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": [{ "ID": "3", "Amount": 4 }]},
{ "ID": "C2", "Name": "Sue", "Country": "USA",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": [{ "ID": "4", "Amount": 8 },
{ "ID": "5", "Amount": 4 }]},
{ "ID": "C3", "Name": "Sue", "Country": "Netherlands",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": []},
{ "ID": "C4", "Name": "Luc", "Country": "France",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": []}
]
}
```
-If `Sales` was a collection-valued complex property of type `SalesModel.SalesComplexType`, the context would be `"FilteredSales@odata.context": "#Collection(SalesModel.SalesComplexType)"`.
+If `Sales` was a collection-valued complex property of type `SalesModel.SalesComplexType`, the context would be `"FilteredSales@context": "#Collection(SalesModel.SalesComplexType)"`.
:::
## 3.5 Expressions Evaluable on a Collection
@@ -2072,7 +2072,7 @@ GET /service/Sales?$filter=Amount mul 3 ge $these/aggregate(Amount with sum)
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": "4", "Amount": 8 }
]
@@ -2097,7 +2097,7 @@ GET /service/Products?$filter=Sales/any(s:s/Amount ge
Both examples result in
```json
{
- "@odata.context": "$metadata#Products",
+ "@context": "$metadata#Products",
"value": [
{ "ID": "P3", "Name": "Paper", "Color": "White", "TaxRate": 0.14 }
]
@@ -2117,7 +2117,7 @@ GET /service/Sales?$apply=topcount($these/$count div 3,Amount)
results in 2 (a third of 8, rounded down) entities. (This differs from `toppercent(33.3,Amount)`, which returns only the sales entity with `ID` 4, because that already makes up a third of the total amount.)
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 3, "Amount": 4 },
{ "ID": 4, "Amount": 8 }
@@ -2143,7 +2143,7 @@ GET /service/Sales?$apply=aggregate(Amount with sum as Total)
results in
```json
{
- "@odata.context": "$metadata#Sales(Total)",
+ "@context": "$metadata#Sales(Total)",
"value": []
}
```
@@ -2162,16 +2162,16 @@ GET /service/Products
results in
```json
{
- "@odata.context":"$metadata#Products(Sales(Total))",
+ "@context":"$metadata#Products(Sales(Total))",
"value": [
{ "ID": "P2", "Name": "Coffee", "Color": "Brown", "TaxRate": 0.06,
- "Sales": [ { "Total@odata.type": "Decimal", "Total": 12 } ] },
+ "Sales": [ { "Total@type": "Decimal", "Total": 12 } ] },
{ "ID": "P3", "Name": "Paper", "Color": "White", "TaxRate": 0.14,
- "Sales": [ { "Total@odata.type": "Decimal", "Total": 8 } ] },
+ "Sales": [ { "Total@type": "Decimal", "Total": 8 } ] },
{ "ID": "P4", "Name": "Pencil", "Color": "Black", "TaxRate": 0.14,
"Sales": [ { "Total": null } ] },
{ "ID": "P1", "Name": "Sugar", "Color": "White", "TaxRate": 0.06,
- "Sales": [ { "Total@odata.type": "Decimal", "Total": 4 } ] }
+ "Sales": [ { "Total@type": "Decimal", "Total": 4 } ] }
]
}
```
@@ -2201,7 +2201,7 @@ GET /service/$crossjoin(Products,Sales)
results in
```json
{
- "@odata.context": "$metadata#Collection(Edm.ComplexType)",
+ "@context": "$metadata#Collection(Edm.ComplexType)",
"value": [
{ "Products": { "Name": "Paper" }, "Sales": { "Amount": 1 } },
{ "Products": { "Name": "Sugar" }, "Sales": { "Amount": 2 } },
@@ -2223,17 +2223,17 @@ GET /service/$crossjoin(Products,Sales)
results in
```json
{
- "@odata.context": "$metadata#Collection(Edm.ComplexType)",
+ "@context": "$metadata#Collection(Edm.ComplexType)",
"value": [
{ "Products": { "Name": "Coffee" },
- "AggregatedSales@odata.context": "#Sales(Total)",
- "AggregatedSales": { "Total@odata.type": "Decimal", "Total": 12 } },
+ "AggregatedSales@context": "#Sales(Total)",
+ "AggregatedSales": { "Total@type": "Decimal", "Total": 12 } },
{ "Products": { "Name": "Paper" },
- "AggregatedSales@odata.context": "#Sales(Total)",
- "AggregatedSales": { "Total@odata.type": "Decimal", "Total": 8 } },
+ "AggregatedSales@context": "#Sales(Total)",
+ "AggregatedSales": { "Total@type": "Decimal", "Total": 8 } },
{ "Products": { "Name": "Sugar" },
- "AggregatedSales@odata.context": "#Sales(Total)",
- "AggregatedSales": { "Total@odata.type": "Decimal", "Total": 4 } }
+ "AggregatedSales@context": "#Sales(Total)",
+ "AggregatedSales": { "Total@type": "Decimal", "Total": 4 } }
]
}
```
@@ -2505,7 +2505,7 @@ GET /service/SalesOrganizations?$filter=Aggregation.isdescendant(
results in
```json
{
- "@odata.context": "$metadata#SalesOrganizations",
+ "@context": "$metadata#SalesOrganizations",
"value": [
{ "ID": "EMEA Central", "Name": "EMEA Central" },
{ "ID": "Sales Netherlands", "Name": "Sales Netherlands" },
@@ -2532,7 +2532,7 @@ GET /service/SalesOrganizations?$filter=Aggregation.isdescendant(
results in
```json
{
- "@odata.context": "$metadata#SalesOrganizations",
+ "@context": "$metadata#SalesOrganizations",
"value": [
{ "ID": "EMEA Central", "Name": "EMEA Central" },
{ "ID": "EMEA South", "Name": "EMEA South" },
@@ -2554,7 +2554,7 @@ GET /service/SalesOrganizations?$filter=Aggregation.isleaf(
results in
```json
{
- "@odata.context": "$metadata#SalesOrganizations",
+ "@context": "$metadata#SalesOrganizations",
"value": [
{ "ID": "Sales Office London", "Name": "Sales Office London" },
{ "ID": "Sales Office New York", "Name": "Sales Office New York" },
@@ -2576,7 +2576,7 @@ GET /service/SalesOrganizations?$filter=Aggregation.isleaf(
results in
```json
{
- "@odata.context": "$metadata#SalesOrganizations(*,Superordinate(ID))",
+ "@context": "$metadata#SalesOrganizations(*,Superordinate(ID))",
"value": [
{ "ID": "Sales Office London", "Name": "Sales Office London",
"Superordinate": { "ID": "EMEA United Kingdom" } },
@@ -2601,7 +2601,7 @@ GET /service/Sales?$select=ID&$filter=Aggregation.isdescendant(
results in
```json
{
- "@odata.context": "$metadata#Sales(ID)",
+ "@context": "$metadata#Sales(ID)",
"value": [
{ "ID": 6 },
{ "ID": 7 },
@@ -2687,12 +2687,12 @@ GET /service/SalesOrganizations?$apply=
results in
```json
{
- "@odata.context": "$metadata#SalesOrganizations",
+ "@context": "$metadata#SalesOrganizations",
"value": [
{ "ID": "EMEA", "Name": "EMEA",
- "Superordinate": { "@odata.id": "SalesOrganizations('Sales')" } },
+ "Superordinate": { "@id": "SalesOrganizations('Sales')" } },
{ "ID": "US", "Name": "US",
- "Superordinate": { "@odata.id": "SalesOrganizations('Sales')" } },
+ "Superordinate": { "@id": "SalesOrganizations('Sales')" } },
{ "ID": "Sales", "Name": "Sales",
"Superordinate": null }
]
@@ -2711,14 +2711,14 @@ GET /service/SalesOrganizations?$apply=
results in
```json
{
- "@odata.context": "$metadata#SalesOrganizations",
+ "@context": "$metadata#SalesOrganizations",
"value": [
{ "ID": "US West", "Name": "US West",
- "Superordinate": { "@odata.id": "SalesOrganizations('US')" } },
+ "Superordinate": { "@id": "SalesOrganizations('US')" } },
{ "ID": "US", "Name": "US",
- "Superordinate": { "@odata.id": "SalesOrganizations('Sales')" } },
+ "Superordinate": { "@id": "SalesOrganizations('Sales')" } },
{ "ID": "US East", "Name": "US East",
- "Superordinate": { "@odata.id": "SalesOrganizations('US')" } }
+ "Superordinate": { "@id": "SalesOrganizations('US')" } }
]
}
```
@@ -2738,7 +2738,7 @@ GET /service/Sales?$apply=
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": "4", "Amount": 8,
"SalesOrganization": { "ID": "US East", "Name": "US East" } },
@@ -2828,12 +2828,12 @@ GET /service/SalesOrganizations?$apply=
results in
```json
{
- "@odata.context": "$metadata#SalesOrganizations",
+ "@context": "$metadata#SalesOrganizations",
"value": [
{ "ID": "US", "Name": "US",
- "Superordinate": { "@odata.id": "SalesOrganizations('Sales')" } },
+ "Superordinate": { "@id": "SalesOrganizations('Sales')" } },
{ "ID": "US East", "Name": "US East",
- "Superordinate": { "@odata.id": "SalesOrganizations('US')" } }
+ "Superordinate": { "@id": "SalesOrganizations('US')" } }
]
}
```
@@ -2910,7 +2910,7 @@ GET /service/SalesOrganizations?$apply=
results in
```json
{
- "@odata.context":
+ "@context":
"$metadata#SalesOrganizations(ID,Name,SubOrgCnt,Superordinate(ID))",
"value": [
{ "ID": "US West", "Name": "US West",
@@ -2951,18 +2951,18 @@ GET /service/Sales?$apply=groupby(
results in
```json
{
- "@odata.context": "$metadata#Sales(SalesOrganization(),
+ "@context": "$metadata#Sales(SalesOrganization(),
TotalAmountIncl,TotalAmountExcl)",
"value": [
{ "SalesOrganization": { "ID": "US West", "Name": "US West" },
- "TotalAmountIncl@odata.type": "Decimal", "TotalAmountIncl": 7,
- "TotalAmountExcl@odata.type": "Decimal" ,"TotalAmountExcl": 7 },
+ "TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 7,
+ "TotalAmountExcl@type": "Decimal" ,"TotalAmountExcl": 7 },
{ "SalesOrganization": { "ID": "US", "Name": "US" },
- "TotalAmountIncl@odata.type": "Decimal", "TotalAmountIncl": 19,
+ "TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 19,
"TotalAmountExcl": null },
{ "SalesOrganization": { "ID": "US East", "Name": "US East" },
- "TotalAmountIncl@odata.type": "Decimal", "TotalAmountIncl": 12,
- "TotalAmountExcl@odata.type": "Decimal", "TotalAmountExcl": 12 }
+ "TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 12,
+ "TotalAmountExcl@type": "Decimal", "TotalAmountExcl": 12 }
]
}
```
@@ -2979,7 +2979,7 @@ GET /service/Sales?$apply=
results in
```json
{
- "@odata.context": "$metadata#Sales(SalesOrganization(),TotalAmount)",
+ "@context": "$metadata#Sales(SalesOrganization(),TotalAmount)",
"value": [
{ "SalesOrganization": { "ID": "Sales", "Name": "Corporate Sales" },
"TotalAmount": null },
@@ -3021,7 +3021,7 @@ GET /service/Customers?$apply=groupby((Name))
results in
```json
{
- "@odata.context": "$metadata#Customers(Name)",
+ "@context": "$metadata#Customers(Name)",
"value": [
{ "Name": "Luc" },
{ "Name": "Joe" },
@@ -3043,7 +3043,7 @@ GET /service/Sales?$apply=groupby((Customer/Name))
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Name))",
+ "@context": "$metadata#Sales(Customer(Name))",
"value": [
{ "Customer": { "Name": "Joe" } },
{ "Customer": { "Name": "Sue" } }
@@ -3066,7 +3066,7 @@ GET /service/Sales?$apply=groupby((Customer/Name,Customer/ID))
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Name,ID))",
+ "@context": "$metadata#Sales(Customer(Name,ID))",
"value": [
{ "Customer": { "Name": "Joe", "ID": "C1" } },
{ "Customer": { "Name": "Sue", "ID": "C2" } },
@@ -3090,7 +3090,7 @@ GET /service/Sales?$apply=groupby((Customer))
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer())",
+ "@context": "$metadata#Sales(Customer())",
"value": [
{ "Customer": { "ID": "C1", "Name": "Joe", "Country": "USA" } },
{ "Customer": { "ID": "C2", "Name": "Sue", "Country": "USA" } },
@@ -3108,7 +3108,7 @@ GET /service/Sales?$apply=groupby((Customer/Name,Customer/ID,Product/Name))
and results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Name,ID),Product(Name))",
+ "@context": "$metadata#Sales(Customer(Name,ID),Product(Name))",
"value": [
{ "Customer": { "Name": "Joe", "ID": "C1" },
"Product": { "Name": "Coffee"} },
@@ -3138,13 +3138,13 @@ GET /service/Products?$apply=groupby((SalesModel.FoodProduct/Rating,
results in
```json
{
- "@odata.context": "$metadata#Products(SalesModel.FoodProduct/Rating,
+ "@context": "$metadata#Products(SalesModel.FoodProduct/Rating,
SalesModel.NonFoodProduct/RatingClass)",
"value": [
- { "@odata.type": "#SalesModel.FoodProduct", "Rating": 5 },
- { "@odata.type": "#SalesModel.FoodProduct", "Rating": null },
- { "@odata.type": "#SalesModel.NonFoodProduct", "RatingClass": "average" },
- { "@odata.type": "#SalesModel.NonFoodProduct", "RatingClass": null }
+ { "@type": "#SalesModel.FoodProduct", "Rating": 5 },
+ { "@type": "#SalesModel.FoodProduct", "Rating": null },
+ { "@type": "#SalesModel.NonFoodProduct", "RatingClass": "average" },
+ { "@type": "#SalesModel.NonFoodProduct", "RatingClass": null }
]
}
```
@@ -3158,10 +3158,10 @@ GET /service/Products?$apply=groupby((SalesModel.FoodProduct/Rating))
results in a third group representing entities with no `SalesModel.FoodProduct/Rating`, including the `SalesModel.NonFoodProduct`s:
```json
{
- "@odata.context": "$metadata#Products(@Core.AnyStructure)",
+ "@context": "$metadata#Products(@Core.AnyStructure)",
"value": [
- { "@odata.type": "#SalesModel.FoodProduct", "Rating": 5 },
- { "@odata.type": "#SalesModel.FoodProduct", "Rating": null },
+ { "@type": "#SalesModel.FoodProduct", "Rating": 5 },
+ { "@type": "#SalesModel.FoodProduct", "Rating": null },
{ }
]
}
@@ -3181,12 +3181,12 @@ GET /service/Products?$apply=groupby((Name),
results in
```json
{
- "@odata.context": "$metadata#Products(Name,Total)",
+ "@context": "$metadata#Products(Name,Total)",
"value": [
- { "Name": "Coffee", "Total@odata.type": "Decimal", "Total": 12 },
- { "Name": "Paper", "Total@odata.type": "Decimal", "Total": 8 },
+ { "Name": "Coffee", "Total@type": "Decimal", "Total": 12 },
+ { "Name": "Paper", "Total@type": "Decimal", "Total": 8 },
{ "Name": "Pencil", "Total": null },
- { "Name": "Sugar", "Total@odata.type": "Decimal", "Total": 4 }
+ { "Name": "Sugar", "Total@type": "Decimal", "Total": 4 }
]
}
```
@@ -3203,20 +3203,20 @@ GET /service/Products?$apply=addnested(Sales,
results in
```json
{
- "@odata.context": "$metadata#Products(AggregatedSales())",
+ "@context": "$metadata#Products(AggregatedSales())",
"value": [
{ "ID": "P2", "Name": "Coffee", "Color": "Brown", "TaxRate": 0.06,
- "AggregatedSales@odata.context": "#Sales(Total)",
- "AggregatedSales": [ { "Total@odata.type": "Decimal", "Total": 12 } ] },
+ "AggregatedSales@context": "#Sales(Total)",
+ "AggregatedSales": [ { "Total@type": "Decimal", "Total": 12 } ] },
{ "ID": "P3", "Name": "Paper", "Color": "White", "TaxRate": 0.14,
- "AggregatedSales@odata.context": "#Sales(Total)",
- "AggregatedSales": [ { "Total@odata.type": "Decimal", "Total": 8 } ] },
+ "AggregatedSales@context": "#Sales(Total)",
+ "AggregatedSales": [ { "Total@type": "Decimal", "Total": 8 } ] },
{ "ID": "P4", "Name": "Pencil", "Color": "Black", "TaxRate": 0.14,
- "AggregatedSales@odata.context": "#Sales(Total)",
+ "AggregatedSales@context": "#Sales(Total)",
"AggregatedSales": [ { "Total": null } ] },
{ "ID": "P1", "Name": "Sugar", "Color": "White", "TaxRate": 0.06,
- "AggregatedSales@odata.context": "#Sales(Total)",
- "AggregatedSales": [ { "Total@odata.type": "Decimal", "Total": 4 } ] }
+ "AggregatedSales@context": "#Sales(Total)",
+ "AggregatedSales": [ { "Total@type": "Decimal", "Total": 4 } ] }
]
}
```
@@ -3230,16 +3230,16 @@ GET /service/Products?$compute=Sales/aggregate(Amount with sum) as Total
results in
```json
{
- "@odata.context": "$metadata#Products(*,Total)",
+ "@context": "$metadata#Products(*,Total)",
"value": [
{ "ID": "P2", "Name": "Coffee", "Color": "Brown", "TaxRate": 0.06,
- "Total@odata.type": "Decimal", "Total": 12 },
+ "Total@type": "Decimal", "Total": 12 },
{ "ID": "P3", "Name": "Paper", "Color": "White", "TaxRate": 0.14,
- "Total@odata.type": "Decimal", "Total": 8 },
+ "Total@type": "Decimal", "Total": 8 },
{ "ID": "P4", "Name": "Pencil", "Color": "Black", "TaxRate": 0.14,
"Total": null },
{ "ID": "P1", "Name": "Sugar", "Color": "White", "TaxRate": 0.06,
- "Total@odata.type": "Decimal", "Total": 4 }
+ "Total@type": "Decimal", "Total": 4 }
]
}
```
@@ -3257,17 +3257,17 @@ GET /service/Products?$apply=
results in
```json
{
- "@odata.context": "$metadata#Products(Name,TotalSales())",
+ "@context": "$metadata#Products(Name,TotalSales())",
"value": [
{ "Name": "Coffee",
- "TotalSales@odata.context": "#Sales(Total)/$entity",
- "TotalSales": { "Total@odata.type": "Decimal", "Total": 12 } },
+ "TotalSales@context": "#Sales(Total)/$entity",
+ "TotalSales": { "Total@type": "Decimal", "Total": 12 } },
{ "Name": "Paper",
- "TotalSales@odata.context": "#Sales(Total)/$entity",
- "TotalSales": { "Total@odata.type": "Decimal", "Total": 8 } },
+ "TotalSales@context": "#Sales(Total)/$entity",
+ "TotalSales": { "Total@type": "Decimal", "Total": 8 } },
{ "Name": "Sugar",
- "TotalSales@odata.context": "#Sales(Total)/$entity",
- "TotalSales": { "Total@odata.type": "Decimal", "Total": 4 } }
+ "TotalSales@context": "#Sales(Total)/$entity",
+ "TotalSales": { "Total@type": "Decimal", "Total": 4 } }
]
}
```
@@ -3284,7 +3284,7 @@ GET /service/Sales?$apply=groupby((Customer/Country),
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Country),AverageAmount)",
+ "@context": "$metadata#Sales(Customer(Country),AverageAmount)",
"value": [
{ "Customer": { "Country": "Netherlands" },
"AverageAmount": 1.6666666666666667 },
@@ -3305,12 +3305,12 @@ GET /service/Products?$apply=groupby((Name),
results in
```json
{
- "@odata.context": "$metadata#Products(Name,SalesCount)",
+ "@context": "$metadata#Products(Name,SalesCount)",
"value": [
- { "Name": "Coffee", "SalesCount@odata.type": "Decimal", "SalesCount": 2 },
- { "Name": "Paper", "SalesCount@odata.type": "Decimal", "SalesCount": 4 },
- { "Name": "Pencil", "SalesCount@odata.type": "Decimal", "SalesCount": 0 },
- { "Name": "Sugar", "SalesCount@odata.type": "Decimal", "SalesCount": 2 }
+ { "Name": "Coffee", "SalesCount@type": "Decimal", "SalesCount": 2 },
+ { "Name": "Paper", "SalesCount@type": "Decimal", "SalesCount": 4 },
+ { "Name": "Pencil", "SalesCount@type": "Decimal", "SalesCount": 0 },
+ { "Name": "Sugar", "SalesCount@type": "Decimal", "SalesCount": 2 }
]
}
```
@@ -3328,23 +3328,23 @@ GET /service/Products?$apply=groupby((Name),addnested(Sales,
results in
```json
{
- "@odata.context": "$metadata#Products(Name,AggregatedSales())",
+ "@context": "$metadata#Products(Name,AggregatedSales())",
"value": [
{ "Name": "Coffee",
- "AggregatedSales@odata.context": "#Sales(SalesCount,TotalAmount)",
+ "AggregatedSales@context": "#Sales(SalesCount,TotalAmount)",
"AggregatedSales": [ { "SalesCount": 2,
- "TotalAmount@odata.type": "Decimal", "TotalAmount": 12 } ] },
+ "TotalAmount@type": "Decimal", "TotalAmount": 12 } ] },
{ "Name": "Paper",
- "AggregatedSales@odata.context": "#Sales(SalesCount,TotalAmount)",
+ "AggregatedSales@context": "#Sales(SalesCount,TotalAmount)",
"AggregatedSales": [ { "SalesCount": 4,
- "TotalAmount@odata.type": "Decimal", "TotalAmount": 8 } ] },
+ "TotalAmount@type": "Decimal", "TotalAmount": 8 } ] },
{ "Name": "Pencil",
- "AggregatedSales@odata.context": "#Sales(SalesCount,TotalAmount)",
+ "AggregatedSales@context": "#Sales(SalesCount,TotalAmount)",
"AggregatedSales": [ { "SalesCount": 0, "TotalAmount": null } ] },
{ "Name": "Sugar",
- "AggregatedSales@odata.context": "#Sales(SalesCount,TotalAmount)",
+ "AggregatedSales@context": "#Sales(SalesCount,TotalAmount)",
"AggregatedSales": [ { "SalesCount": 2,
- "TotalAmount@odata.type": "Decimal", "TotalAmount": 4 } ] }
+ "TotalAmount@type": "Decimal", "TotalAmount": 4 } ] }
]
}
```
@@ -3360,7 +3360,7 @@ GET /service/Products?$filter=Sales/aggregate(Amount with sum) ge 10
results in
```json
{
- "@odata.context": "$metadata#Products",
+ "@context": "$metadata#Products",
"value": [
{ "ID": "P2", "Name": "Coffee", "Color": "Brown", "TaxRate": 0.06 },
{ "ID": "P3", "Name": "Paper", "Color": "White", "TaxRate": 0.14 }
@@ -3377,7 +3377,7 @@ GET /service/Customers?$orderby=Sales/aggregate(Amount with sum) desc
results in
```json
{
- "@odata.context": "$metadata#Customers",
+ "@context": "$metadata#Customers",
"value": [
{ "ID": "C2", "Name": "Sue", "Country": "USA" },
{ "ID": "C1", "Name": "Joe", "Country": "USA" },
@@ -3397,23 +3397,23 @@ GET /service/Sales?$compute=Amount divby $these/aggregate(Amount with sum)
results in
```json
{
- "@odata.context": "$metadata#Sales(*,Contribution)",
+ "@context": "$metadata#Sales(*,Contribution)",
"value": [
- { "ID": 1, "Amount": 1, "Contribution@odata.type": "Decimal",
+ { "ID": 1, "Amount": 1, "Contribution@type": "Decimal",
"Contribution": 0.0416666666666667 },
- { "ID": 2, "Amount": 2, "Contribution@odata.type": "Decimal",
+ { "ID": 2, "Amount": 2, "Contribution@type": "Decimal",
"Contribution": 0.0833333333333333 },
- { "ID": 3, "Amount": 4, "Contribution@odata.type": "Decimal",
+ { "ID": 3, "Amount": 4, "Contribution@type": "Decimal",
"Contribution": 0.1666666666666667 },
- { "ID": 4, "Amount": 8, "Contribution@odata.type": "Decimal",
+ { "ID": 4, "Amount": 8, "Contribution@type": "Decimal",
"Contribution": 0.3333333333333333 },
- { "ID": 5, "Amount": 4, "Contribution@odata.type": "Decimal",
+ { "ID": 5, "Amount": 4, "Contribution@type": "Decimal",
"Contribution": 0.1666666666666667 },
- { "ID": 6, "Amount": 2, "Contribution@odata.type": "Decimal",
+ { "ID": 6, "Amount": 2, "Contribution@type": "Decimal",
"Contribution": 0.0833333333333333 },
- { "ID": 7, "Amount": 1, "Contribution@odata.type": "Decimal",
+ { "ID": 7, "Amount": 1, "Contribution@type": "Decimal",
"Contribution": 0.0416666666666667 },
- { "ID": 8, "Amount": 2, "Contribution@odata.type": "Decimal",
+ { "ID": 8, "Amount": 2, "Contribution@type": "Decimal",
"Contribution": 0.0833333333333333 }
]
}
@@ -3429,7 +3429,7 @@ GET /service/Categories?$filter=Products/any(
results in
```json
{
- "@odata.context": "$metadata#Categories",
+ "@context": "$metadata#Categories",
"value": [
{ "ID": "PG1", "Name": "Food" }
]
@@ -3451,14 +3451,14 @@ GET /service/Sales?$apply=
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(),CustomerAmount,Contribution)",
+ "@context": "$metadata#Sales(Customer(),CustomerAmount,Contribution)",
"value": [
- { "Customer": { "@odata.id": "Customers('C1')" },
- "Contribution@odata.type": "Decimal", "Contribution": 0.2916667 },
- { "Customer": { "@odata.id": "Customers('C2')" },
- "Contribution@odata.type": "Decimal", "Contribution": 0.5 },
- { "Customer": { "@odata.id": "Customers('C3')" },
- "Contribution@odata.type": "Decimal", "Contribution": 0.2083333 }
+ { "Customer": { "@id": "Customers('C1')" },
+ "Contribution@type": "Decimal", "Contribution": 0.2916667 },
+ { "Customer": { "@id": "Customers('C2')" },
+ "Contribution@type": "Decimal", "Contribution": 0.5 },
+ { "Customer": { "@id": "Customers('C3')" },
+ "Contribution@type": "Decimal", "Contribution": 0.2083333 }
]
}
```
@@ -3502,18 +3502,18 @@ GET /service/Customers?$apply=
results in
```json
{
- "@odata.context": "$metadata#Customers(
+ "@context": "$metadata#Customers(
Addresses(AugmentedSalesOrganization())",
"value": [
{ "ID": "C1", "Name": "Joe", "Country": "US",
"Addresses": [
{ "Locality": "Seattle",
"AugmentedSalesOrganization":
- { "@odata.context": "#SalesOrganizations/$entity",
+ { "@context": "#SalesOrganizations/$entity",
"ID": "US West", "SalesRegion": "US" } },
{ "Locality": "DC",
"AugmentedSalesOrganization":
- { "@odata.context": "#SalesOrganizations/$entity",
+ { "@context": "#SalesOrganizations/$entity",
"ID": "US", "SalesRegion": "Corporate Sales" } },
]
}, ...
@@ -3535,28 +3535,28 @@ GET /service/Categories?$apply=
results in
```json
{
- "@odata.context": "$metadata#Categories(FilteredProducts()",
+ "@context": "$metadata#Categories(FilteredProducts()",
"value": [
{ "ID": "PG1", "Name": "Food",
- "FilteredProducts@odata.context": "#Products(FilteredSales())",
+ "FilteredProducts@context": "#Products(FilteredSales())",
"FilteredProducts": [
{ "ID": "P1", "Name": "Sugar", "Color": "White",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": [] },
{ "ID": "P2", "Name": "Coffee", "Color": "Brown",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": [ { "ID": 3, "Amount": 4 },
{ "ID": 4, "Amount": 8 } ] }
]
},
{ "ID": "PG2", "Name": "Non-Food",
- "FilteredProducts@odata.context": "#Products(FilteredSales())",
+ "FilteredProducts@context": "#Products(FilteredSales())",
"FilteredProducts": [
{ "ID": "P3", "Name": "Paper", "Color": "White",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": [ { "ID": 5, "Amount": 4 } ] },
{ "ID": "P4", "Name": "Pencil", "Color": "Black",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": [] }
]
}
@@ -3585,29 +3585,29 @@ GET /service/Customers?$apply=addnested(Sales,
results in
```json
{
- "@odata.context": "$metadata#Customers(GroupedSales())",
+ "@context": "$metadata#Customers(GroupedSales())",
"value": [
{ "ID": "C1", "Name": "Joe", "Country": "USA",
- "GroupedSales@odata.context": "#Sales(@Core.AnyStructure)",
+ "GroupedSales@context": "#Sales(@Core.AnyStructure)",
"GroupedSales": [
{ },
{ },
{ }
] },
{ "ID": "C2", "Name": "Sue", "Country": "USA",
- "GroupedSales@odata.context": "#Sales(@Core.AnyStructure)",
+ "GroupedSales@context": "#Sales(@Core.AnyStructure)",
"GroupedSales": [
{ },
{ }
] },
{ "ID": "C3", "Name": "Joe", "Country": "Netherlands",
- "GroupedSales@odata.context": "#Sales(@Core.AnyStructure)",
+ "GroupedSales@context": "#Sales(@Core.AnyStructure)",
"GroupedSales": [
{ },
{ }
] },
{ "ID": "C4", "Name": "Luc", "Country": "France",
- "GroupedSales@odata.context": "#Sales(@Core.AnyStructure)",
+ "GroupedSales@context": "#Sales(@Core.AnyStructure)",
"GroupedSales": [ ] }
]
}
@@ -3623,22 +3623,22 @@ GET /service/Customers?$apply=outerjoin(Sales as ProductSales)
returns the different combinations of products sold per country:
```json
{
- "@odata.context":"$metadata#Customers(Country,ProductSales())",
+ "@context":"$metadata#Customers(Country,ProductSales())",
"value": [
{ "Country": "Netherlands",
- "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
+ "ProductSales@context": "#Sales(Product(Name))/$entity",
"ProductSales": { "Product": { "Name": "Paper" } } },
{ "Country": "Netherlands",
- "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
+ "ProductSales@context": "#Sales(Product(Name))/$entity",
"ProductSales": { "Product": { "Name": "Sugar" } } },
{ "Country": "USA",
- "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
+ "ProductSales@context": "#Sales(Product(Name))/$entity",
"ProductSales": { "Product": { "Name": "Coffee" } } },
{ "Country": "USA",
- "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
+ "ProductSales@context": "#Sales(Product(Name))/$entity",
"ProductSales": { "Product": { "Name": "Paper" } } },
{ "Country": "USA",
- "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
+ "ProductSales@context": "#Sales(Product(Name))/$entity",
"ProductSales": { "Product": { "Name": "Sugar" } } },
{ "Country": "France", "ProductSales": null }
]
@@ -3660,14 +3660,14 @@ GET /service/Sales?$apply=groupby((Customer/Country),
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Country),Actual,Forecast)",
+ "@context": "$metadata#Sales(Customer(Country),Actual,Forecast)",
"value": [
{ "Customer": { "Country": "Netherlands" },
- "Actual@odata.type": "Decimal", "Actual": 5,
- "Forecast@odata.type": "Decimal", "Forecast": 4 },
+ "Actual@type": "Decimal", "Actual": 5,
+ "Forecast@type": "Decimal", "Forecast": 4 },
{ "Customer": { "Country": "USA" },
- "Actual@odata.type": "Decimal", "Actual": 19,
- "Forecast@odata.type": "Decimal", "Forecast": 21 }
+ "Actual@type": "Decimal", "Actual": 19,
+ "Forecast@type": "Decimal", "Forecast": 21 }
]
}
```
@@ -3683,7 +3683,7 @@ GET /service/Sales?$apply=groupby((Customer/Country),aggregate(Amount))
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Country),Amount)",
+ "@context": "$metadata#Sales(Customer(Country),Amount)",
"value": [
{ "Customer": { "Country": "Netherlands" }, "Amount": 5 },
{ "Customer": { "Country": "USA" }, "Amount": 19 }
@@ -3750,14 +3750,14 @@ GET /service/Sales?$apply=groupby((Customer/Country),
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Country),Total,AvgAmt)",
+ "@context": "$metadata#Sales(Customer(Country),Total,AvgAmt)",
"value": [
{ "Customer": { "Country": "Netherlands" },
- "Total@odata.type": "Decimal", "Total": 5,
- "AvgAmt@odata.type": "Decimal", "AvgAmt": 1.6666667 },
+ "Total@type": "Decimal", "Total": 5,
+ "AvgAmt@type": "Decimal", "AvgAmt": 1.6666667 },
{ "Customer": { "Country": "USA" },
- "Total@odata.type": "Decimal", "Total": 19,
- "AvgAmt@odata.type": "Decimal", "AvgAmt": 3.8 }
+ "Total@type": "Decimal", "Total": 19,
+ "AvgAmt@type": "Decimal", "AvgAmt": 3.8 }
]
}
```
@@ -3777,22 +3777,22 @@ GET /service/Products?$apply=groupby((Name),
results in
```json
{
- "@odata.context": "$metadata#Products(Name,Total,AggregatedSales())",
+ "@context": "$metadata#Products(Name,Total,AggregatedSales())",
"value": [
{ "Name": "Coffee", "Total": 12,
- "AggregatedSales@odata.context": "#Sales(AvgAmt)",
- "AggregatedSales": [ { "AvgAmt@odata.type": "Decimal",
+ "AggregatedSales@context": "#Sales(AvgAmt)",
+ "AggregatedSales": [ { "AvgAmt@type": "Decimal",
"AvgAmt": 6 } ] },
{ "Name": "Paper", "Total": 8,
- "AggregatedSales@odata.context": "#Sales(AvgAmt)",
- "AggregatedSales": [ { "AvgAmt@odata.type": "Decimal",
+ "AggregatedSales@context": "#Sales(AvgAmt)",
+ "AggregatedSales": [ { "AvgAmt@type": "Decimal",
"AvgAmt": 2 } ] },
{ "Name": "Pencil", "Total": null,
- "AggregatedSales@odata.context": "#Sales(AvgAmt)",
+ "AggregatedSales@context": "#Sales(AvgAmt)",
"AggregatedSales": [ { "AvgAmt": null } ] },
{ "Name": "Sugar", "Total": 4,
- "AggregatedSales@odata.context": "#Sales(AvgAmt)",
- "AggregatedSales": [ { "AvgAmt@odata.type": "Decimal",
+ "AggregatedSales@context": "#Sales(AvgAmt)",
+ "AggregatedSales": [ { "AvgAmt@type": "Decimal",
"AvgAmt": 2 } ] }
]
}
@@ -3809,12 +3809,12 @@ GET /service/Sales?$apply=groupby((Amount),aggregate(Amount with sum as Total))
will return all distinct amounts appearing in sales orders and how much money was made with deals of this amount
```json
{
- "@odata.context": "$metadata#Sales(Amount,Total)",
+ "@context": "$metadata#Sales(Amount,Total)",
"value": [
- { "Amount": 1, "Total@odata.type": "Decimal", "Total": 2 },
- { "Amount": 2, "Total@odata.type": "Decimal", "Total": 6 },
- { "Amount": 4, "Total@odata.type": "Decimal", "Total": 8 },
- { "Amount": 8, "Total@odata.type": "Decimal", "Total": 8 }
+ { "Amount": 1, "Total@type": "Decimal", "Total": 2 },
+ { "Amount": 2, "Total@type": "Decimal", "Total": 6 },
+ { "Amount": 4, "Total@type": "Decimal", "Total": 8 },
+ { "Amount": 8, "Total@type": "Decimal", "Total": 8 }
]
}
```
@@ -3837,19 +3837,19 @@ GET /service/Sales?$apply=concat(
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Country),Total)",
+ "@context": "$metadata#Sales(Customer(Country),Total)",
"value": [
{ "Customer":{ "Country": "USA" }, "Product":{ "Name": "Coffee" },
- "Total@odata.type": "Decimal", "Total": 12
+ "Total@type": "Decimal", "Total": 12
},
{ "Customer":{ "Country": "Netherlands" }, "Product":{ "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 3
+ "Total@type": "Decimal", "Total": 3
},
{ "Customer":{ "Country": "USA" },
- "Total@odata.type": "Decimal", "Total": 19
+ "Total@type": "Decimal", "Total": 19
},
{ "Customer":{ "Country": "Netherlands" },
- "Total@odata.type": "Decimal", "Total": 5
+ "Total@type": "Decimal", "Total": 5
}
]
}
@@ -3865,22 +3865,22 @@ GET /service/Sales?$apply=groupby((Customer/Country,Product/Name),
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Country),Product(Name),Total)",
+ "@context": "$metadata#Sales(Customer(Country),Product(Name),Total)",
"value": [
{ "Customer":{ "Country": "Netherlands" }, "Product":{ "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 3
+ "Total@type": "Decimal", "Total": 3
},
{ "Customer":{ "Country": "Netherlands" }, "Product":{ "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 2
+ "Total@type": "Decimal", "Total": 2
},
{ "Customer":{ "Country": "USA" }, "Product":{ "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 2
+ "Total@type": "Decimal", "Total": 2
},
{ "Customer":{ "Country": "USA" }, "Product":{ "Name": "Coffee" },
- "Total@odata.type": "Decimal", "Total": 12
+ "Total@type": "Decimal", "Total": 12
},
{ "Customer":{ "Country": "USA" }, "Product":{ "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 5
+ "Total@type": "Decimal", "Total": 5
}
]
}
@@ -3898,7 +3898,7 @@ GET /service/Sales?$apply=concat(
In the result, `Sales` entities 4 and 6 occur twice each with contradictory values of the dynamic property `per`. If a UI consuming the response presents the two groupings in separate columns based on the `per` property, no contradiction effectively arises.
```json
{
- "@odata.context": "$metadata#Sales(*,per,Customer(ID),Product(ID))",
+ "@context": "$metadata#Sales(*,per,Customer(ID),Product(ID))",
"value": [
{ "Customer": { "ID": "C1" }, "Product": { "ID": "P2" },
"ID": "3", "Amount": 4, "per": "Customer" },
@@ -3944,18 +3944,18 @@ GET /service/Sales?$apply=
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Country),Total)",
+ "@context": "$metadata#Sales(Customer(Country),Total)",
"value": [
{ "Customer": { "Country": "Netherlands" },
"Product": { "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 3 },
+ "Total@type": "Decimal", "Total": 3 },
{ "Customer": { "Country": "Netherlands" },
- "Total@odata.type": "Decimal", "Total": 2 },
+ "Total@type": "Decimal", "Total": 2 },
{ "Customer": { "Country": "USA" },
"Product": { "Name": "Coffee" },
- "Total@odata.type": "Decimal", "Total": 12 },
+ "Total@type": "Decimal", "Total": 12 },
{ "Customer": { "Country": "USA" },
- "Total@odata.type": "Decimal", "Total": 7 }
+ "Total@type": "Decimal", "Total": 7 }
]
}
```
@@ -4003,24 +4003,24 @@ GET /service/Sales?$apply=concat(
results in
```json
{
- "@odata.context": "$metadata#Sales(CustomerCountryAverage)",
+ "@context": "$metadata#Sales(CustomerCountryAverage)",
"value": [
{ "Customer": { "Country": "USA", "ID": "C1" },
- "CustomerCountryAverage@odata.type":"Decimal",
+ "CustomerCountryAverage@type":"Decimal",
"CustomerCountryAverage": 7 },
{ "Customer": { "Country": "USA", "ID": "C2" },
- "CustomerCountryAverage@odata.type":"Decimal",
+ "CustomerCountryAverage@type":"Decimal",
"CustomerCountryAverage": 12 },
{ "Customer": { "Country": "USA" },
- "CustomerCountryAverage@odata.type":"Decimal",
+ "CustomerCountryAverage@type":"Decimal",
"CustomerCountryAverage": 9.5 },
{ "Customer": { "Country": "Netherlands", "ID": "C3" },
- "CustomerCountryAverage@odata.type":"Decimal",
+ "CustomerCountryAverage@type":"Decimal",
"CustomerCountryAverage": 5 },
{ "Customer": { "Country": "Netherlands" },
- "CustomerCountryAverage@odata.type":"Decimal",
+ "CustomerCountryAverage@type":"Decimal",
"CustomerCountryAverage": 5 },
- { "CustomerCountryAverage@odata.type":"Decimal",
+ { "CustomerCountryAverage@type":"Decimal",
"CustomerCountryAverage": 7.25 }
]
}
@@ -4049,17 +4049,17 @@ GET /service/Sales?$apply=
results in
```json
{
- "@odata.context": "$metadata#Sales(TotalAmount,SalesOrganization())",
+ "@context": "$metadata#Sales(TotalAmount,SalesOrganization())",
"value": [
- { "TotalAmount@odata.type": "Decimal", "TotalAmount": 19,
+ { "TotalAmount@type": "Decimal", "TotalAmount": 19,
"SalesOrganization": { "ID": "US", "Name": "US",
- "Superordinate": { "@odata.id": "SalesOrganizations('Sales')" } } },
- { "TotalAmount@odata.type": "Decimal", "TotalAmount": 12,
+ "Superordinate": { "@id": "SalesOrganizations('Sales')" } } },
+ { "TotalAmount@type": "Decimal", "TotalAmount": 12,
"SalesOrganization": { "ID": "US East", "Name": "US East",
- "Superordinate": { "@odata.id": "SalesOrganizations('US')" } } },
- { "TotalAmount@odata.type": "Decimal", "TotalAmount": 7,
+ "Superordinate": { "@id": "SalesOrganizations('US')" } } },
+ { "TotalAmount@type": "Decimal", "TotalAmount": 7,
"SalesOrganization": { "ID": "US West", "Name": "US West",
- "Superordinate": { "@odata.id": "SalesOrganizations('US')" } } }
+ "Superordinate": { "@id": "SalesOrganizations('US')" } } }
]
}
```
@@ -4082,24 +4082,24 @@ GET /service/Sales?$apply=
results in
```json
{
- "@odata.context": "$metadata#Sales(PaperSalesCount,SalesOrganization())",
+ "@context": "$metadata#Sales(PaperSalesCount,SalesOrganization())",
"value": [
- { "PaperSalesCount@odata.type": "Decimal", "PaperSalesCount": 2,
+ { "PaperSalesCount@type": "Decimal", "PaperSalesCount": 2,
"SalesOrganization": { "ID": "US", "Name": "US",
- "Superordinate": { "@odata.id": "SalesOrganizations('Sales')" } } },
- { "PaperSalesCount@odata.type": "Decimal", "PaperSalesCount": 1,
+ "Superordinate": { "@id": "SalesOrganizations('Sales')" } } },
+ { "PaperSalesCount@type": "Decimal", "PaperSalesCount": 1,
"SalesOrganization": { "ID": "US East", "Name": "US East",
- "Superordinate": { "@odata.id": "SalesOrganizations('US')" } } },
- { "PaperSalesCount@odata.type": "Decimal", "PaperSalesCount": 1,
+ "Superordinate": { "@id": "SalesOrganizations('US')" } } },
+ { "PaperSalesCount@type": "Decimal", "PaperSalesCount": 1,
"SalesOrganization": { "ID": "US West", "Name": "US West",
- "Superordinate": { "@odata.id": "SalesOrganizations('US')" } } },
- { "PaperSalesCount@odata.type": "Decimal", "PaperSalesCount": 2,
+ "Superordinate": { "@id": "SalesOrganizations('US')" } } },
+ { "PaperSalesCount@type": "Decimal", "PaperSalesCount": 2,
"SalesOrganization": { "ID": "EMEA", "Name": "EMEA",
- "Superordinate": { "@odata.id": "SalesOrganizations('Sales')" } } },
- { "PaperSalesCount@odata.type": "Decimal", "PaperSalesCount": 2,
+ "Superordinate": { "@id": "SalesOrganizations('Sales')" } } },
+ { "PaperSalesCount@type": "Decimal", "PaperSalesCount": 2,
"SalesOrganization": { "ID": "EMEA Central", "Name": "EMEA Central",
- "Superordinate": { "@odata.id": "SalesOrganizations('EMEA')" } } },
- { "PaperSalesCount@odata.type": "Decimal", "PaperSalesCount": 4,
+ "Superordinate": { "@id": "SalesOrganizations('EMEA')" } } },
+ { "PaperSalesCount@type": "Decimal", "PaperSalesCount": 4,
"SalesOrganization": { "ID": "Sales", "Name": "Sales",
"Superordinate": null } }
]
@@ -4195,18 +4195,18 @@ GET /service/Sales?$apply=groupby(
results in
```json
{
- "@odata.context": "$metadata#Sales(SalesOrganization(ID),
+ "@context": "$metadata#Sales(SalesOrganization(ID),
TotalAmountIncl,TotalAmountExcl)",
"value": [
{ "SalesOrganization": { "ID": "US", "Name": "US" },
- "TotalAmountIncl@odata.type": "Decimal", "TotalAmountIncl": 19,
+ "TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 19,
"TotalAmountExcl": null },
{ "SalesOrganization": { "ID": "US East", "Name": "US East" },
- "TotalAmountIncl@odata.type": "Decimal", "TotalAmountIncl": 12,
- "TotalAmountExcl@odata.type": "Decimal", "TotalAmountExcl": 12 },
+ "TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 12,
+ "TotalAmountExcl@type": "Decimal", "TotalAmountExcl": 12 },
{ "SalesOrganization": { "ID": "US West", "Name": "US West" },
- "TotalAmountIncl@odata.type": "Decimal", "TotalAmountIncl": 7,
- "TotalAmountExcl@odata.type": "Decimal" ,"TotalAmountExcl": 7 }
+ "TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 7,
+ "TotalAmountExcl@type": "Decimal" ,"TotalAmountExcl": 7 }
]
}
```
@@ -4227,7 +4227,7 @@ GET /service/Products?$apply=traverse(
The result contains multiple instances of the same `Product` that differ in their `Sales` navigation property even though they agree in their `ID` key property. The node $x$ with $x/{\tt ID}={}$`"US"` has $σ(x)={}$`{"Sales": [{"SalesOrganization": {"ID": "US"}}]}`.
```json
{
- "@odata.context":
+ "@context":
"$metadata#Products(ID,Sales(SalesOrganization(ID)))",
"value": [
{ "ID": "P1", "Sales": [ { "SalesOrganization": { "ID": "Sales" } } ] },
@@ -4265,7 +4265,7 @@ GET /service/Products?$apply=
results in
```json
{
- "@odata.context": "$metadata#Products(Sales(SalesOrganization(ID)),
+ "@context": "$metadata#Products(Sales(SalesOrganization(ID)),
SoldProducts)",
"value": [
{ "Sales": [ { "SalesOrganization": { "ID": "Sales" } } ],
@@ -4319,17 +4319,17 @@ GET /service/Sales?$apply=groupby((rolluprecursive(
results in
```json
{
- "@odata.context": "$metadata#Sales(SalesOrganization(ID),TotalAmount)",
+ "@context": "$metadata#Sales(SalesOrganization(ID),TotalAmount)",
"value": [
{ "SalesOrganization": { "ID": "Sales", "ProductCategories": [ ] },
- "TotalAmount@odata.type": "Decimal", "TotalAmount": 24 },
+ "TotalAmount@type": "Decimal", "TotalAmount": 24 },
{ "SalesOrganization": { "ID": "US", "ProductCategories": [
- { "@odata.id": "ProductCategories('Food')" },
- { "@odata.id": "ProductCategories('Cereals')" } ] },
- "TotalAmount@odata.type": "Decimal", "TotalAmount": 19 },
+ { "@id": "ProductCategories('Food')" },
+ { "@id": "ProductCategories('Cereals')" } ] },
+ "TotalAmount@type": "Decimal", "TotalAmount": 19 },
{ "SalesOrganization": { "ID": "US West", "ProductCategories": [
- { "@odata.id": "ProductCategories('Organic cereals')" } ] },
- "TotalAmount@odata.type": "Decimal", "TotalAmount": 7 }
+ { "@id": "ProductCategories('Organic cereals')" } ] },
+ "TotalAmount@type": "Decimal", "TotalAmount": 7 }
]
}
```
@@ -4362,9 +4362,9 @@ GET /service/Sales?$apply=filter(Amount le 1)
means "filter first, then aggregate", and results in
```json
{
- "@odata.context": "$metadata#Sales(Total)",
+ "@context": "$metadata#Sales(Total)",
"value": [
- { "Total@odata.type": "Decimal", "Total": 2 }
+ { "Total@type": "Decimal", "Total": 2 }
]
}
```
@@ -4382,12 +4382,12 @@ GET /service/Sales?$apply=filter(Amount le 2)/groupby((Product/Name),
results in
```json
{
- "@odata.context": "$metadata#Sales(Product(Name),Total)",
+ "@context": "$metadata#Sales(Product(Name),Total)",
"value": [
{ "Product": { "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 4 },
+ "Total@type": "Decimal", "Total": 4 },
{ "Product": { "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 4 }
+ "Total@type": "Decimal", "Total": 4 }
]
}
```
@@ -4416,13 +4416,13 @@ GET /service/Cities?$apply=groupby((Continent/Name,Country/Name),
results in
```json
{
- "@odata.context": "$metadata#Cities(Continent(Name),Country(Name),
+ "@context": "$metadata#Cities(Continent(Name),Country(Name),
TotalPopulation)",
"value": [
{ "Continent": { "Name": "Asia" }, "Country": { "Name": "China" },
- "TotalPopulation@odata.type": "Int32", "TotalPopulation": 1412000000 },
+ "TotalPopulation@type": "Int32", "TotalPopulation": 1412000000 },
{ "Continent": { "Name": "Asia" }, "Country": { "Name": "India" },
- "TotalPopulation@odata.type": "Int32", "TotalPopulation": 1408000000 },
+ "TotalPopulation@type": "Int32", "TotalPopulation": 1408000000 },
...
]
}
@@ -4512,15 +4512,15 @@ GET /service/Sales?$apply=groupby((Product/Category/ID),
results in
```json
{
- "@odata.context":"$metadata#Sales(Product(Category(ID)),Customers())",
+ "@context":"$metadata#Sales(Product(Category(ID)),Customers())",
"value": [
{ "Product": { "Category": { "ID": "PG1" } },
- "Customers@odata.context": "#Sales(Customer(ID))",
+ "Customers@context": "#Sales(Customer(ID))",
"Customers": [ { "Customer": { "ID": "C1" } },
{ "Customer": { "ID": "C2" } },
{ "Customer": { "ID": "C3" } } ] },
{ "Product": { "Category": { "ID": "PG2" } },
- "Customers@odata.context": "#Sales(Customer(ID))",
+ "Customers@context": "#Sales(Customer(ID))",
"Customers": [ { "Customer": { "ID": "C1" } },
{ "Customer": { "ID": "C2" } },
{ "Customer": { "ID": "C3" } } ] }
diff --git a/odata-data-aggregation-ext/3.2 Basic Aggregation.md b/odata-data-aggregation-ext/3.2 Basic Aggregation.md
index 2a7f86d00..4180c15c8 100644
--- a/odata-data-aggregation-ext/3.2 Basic Aggregation.md
+++ b/odata-data-aggregation-ext/3.2 Basic Aggregation.md
@@ -43,10 +43,10 @@ GET /service/Sales?$apply=aggregate(Amount with sum as Total,
results in
```json
{
- "@odata.context": "$metadata#Sales(Total, MxA)",
+ "@context": "$metadata#Sales(Total, MxA)",
"value": [
- { "Total@odata.type": "Decimal", "Total": 24,
- "MxA@odata.type": "Decimal", "MxA": 8 }
+ { "Total@type": "Decimal", "Total": 24,
+ "MxA@type": "Decimal", "MxA": 8 }
]
}
```
@@ -61,9 +61,9 @@ GET /service/Sales?$apply=aggregate(Amount mul Product/TaxRate
results in
```json
{
- "@odata.context": "$metadata#Sales(Tax)",
+ "@context": "$metadata#Sales(Tax)",
"value": [
- { "Tax@odata.type": "Decimal", "Tax": 2.08 }
+ { "Tax@type": "Decimal", "Tax": 2.08 }
]
}
```
@@ -87,9 +87,9 @@ GET /service/Sales?$apply=aggregate(Amount with sum as Total)
results in
```json
{
- "@odata.context": "$metadata#Sales(Total)",
+ "@context": "$metadata#Sales(Total)",
"value": [
- { "Total@odata.type": "Decimal", "Total": 24 }
+ { "Total@type": "Decimal", "Total": 24 }
]
}
```
@@ -109,9 +109,9 @@ GET /service/Sales?$apply=aggregate(Amount with min as MinAmount)
results in
```json
{
- "@odata.context": "$metadata#Sales(MinAmount)",
+ "@context": "$metadata#Sales(MinAmount)",
"value": [
- { "MinAmount@odata.type": "Decimal", "MinAmount": 1 }
+ { "MinAmount@type": "Decimal", "MinAmount": 1 }
]
}
```
@@ -131,9 +131,9 @@ GET /service/Sales?$apply=aggregate(Amount with max as MaxAmount)
results in
```json
{
- "@odata.context": "$metadata#Sales(MaxAmount)",
+ "@context": "$metadata#Sales(MaxAmount)",
"value": [
- { "MaxAmount@odata.type": "Decimal", "MaxAmount": 8 }
+ { "MaxAmount@type": "Decimal", "MaxAmount": 8 }
]
}
```
@@ -153,9 +153,9 @@ GET /service/Sales?$apply=aggregate(Amount with average as AverageAmount)
results in
```json
{
- "@odata.context": "$metadata#Sales(AverageAmount)",
+ "@context": "$metadata#Sales(AverageAmount)",
"value": [
- { "AverageAmount@odata.type": "Decimal", "AverageAmount": 3.0 }
+ { "AverageAmount@type": "Decimal", "AverageAmount": 3.0 }
]
}
```
@@ -176,9 +176,9 @@ GET /service/Sales?$apply=aggregate(Product with countdistinct
results in
```json
{
- "@odata.context": "$metadata#Sales(DistinctProducts)",
+ "@context": "$metadata#Sales(DistinctProducts)",
"value": [
- { "DistinctProducts@odata.type": "Decimal", "DistinctProducts": 3 }
+ { "DistinctProducts@type": "Decimal", "DistinctProducts": 3 }
]
}
```
@@ -202,13 +202,13 @@ GET /service/Sales?$apply=groupby((Customer/Country),
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Country),Total,ProductNames)",
+ "@context": "$metadata#Sales(Customer(Country),Total,ProductNames)",
"value": [
{ "Customer": { "Country": "Netherlands" },
- "Total@odata.type": "Decimal", "Total": 5,
+ "Total@type": "Decimal", "Total": 5,
"ProductNames": "Paper,Sugar" },
{ "Customer": { "Country": "USA" },
- "Total@odata.type": "Decimal", "Total": 19,
+ "Total@type": "Decimal", "Total": 19,
"ProductNames": "Coffee,Paper,Sugar" }
]
}
@@ -229,9 +229,9 @@ GET /service/Sales?$apply=aggregate($count as SalesCount)
results in
```json
{
- "@odata.context": "$metadata#Sales(SalesCount)",
+ "@context": "$metadata#Sales(SalesCount)",
"value": [
- { "SalesCount@odata.type": "Decimal", "SalesCount": 8 }
+ { "SalesCount@type": "Decimal", "SalesCount": 8 }
]
}
```
@@ -268,9 +268,9 @@ GET /service/Sales?$apply=groupby((Time),aggregate(Amount with sum as Total))
and results in the average sales volume per day
```json
{
- "@odata.context": "$metadata#Sales(DailyAverage)",
+ "@context": "$metadata#Sales(DailyAverage)",
"value": [
- { "DailyAverage@odata.type": "Decimal", "DailyAverage": 3.428571428571429 }
+ { "DailyAverage@type": "Decimal", "DailyAverage": 3.428571428571429 }
]
}
```
@@ -304,7 +304,7 @@ GET /service/Sales?$apply=concat(topcount(2,Amount),
results in
```json
{
- "@odata.context": "$metadata#Sales(Amount)",
+ "@context": "$metadata#Sales(Amount)",
"value": [
{ "ID": 4, "Amount": 8 },
{ "ID": 3, "Amount": 4 },
@@ -362,23 +362,23 @@ GET /service/Sales?$apply=groupby((Customer/Country,Product/Name),
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Country),Product(Name),Total)",
+ "@context": "$metadata#Sales(Customer(Country),Product(Name),Total)",
"value": [
{ "Customer": { "Country": "Netherlands" },
"Product": { "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 3 },
+ "Total@type": "Decimal", "Total": 3 },
{ "Customer": { "Country": "Netherlands" },
"Product": { "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 2 },
+ "Total@type": "Decimal", "Total": 2 },
{ "Customer": { "Country": "USA" },
"Product": { "Name": "Coffee" },
- "Total@odata.type": "Decimal", "Total": 12 },
+ "Total@type": "Decimal", "Total": 12 },
{ "Customer": { "Country": "USA" },
"Product": { "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 5 },
+ "Total@type": "Decimal", "Total": 5 },
{ "Customer": { "Country": "USA" },
"Product": { "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 2 }
+ "Total@type": "Decimal", "Total": 2 }
]
}
```
@@ -394,7 +394,7 @@ GET /service/Sales?$apply=groupby((Product/Name,Amount))
results in
```json
{
- "@odata.context": "$metadata#Sales(Product(Name),Amount)",
+ "@context": "$metadata#Sales(Product(Name),Amount)",
"value": [
{ "Product": { "Name": "Coffee" }, "Amount": 4 },
{ "Product": { "Name": "Coffee" }, "Amount": 8 },
@@ -463,33 +463,33 @@ GET /service/Sales?$apply=groupby((rollup(Customer/Country,Customer/Name),
results in seven entities for the finest grouping level
```json
{
- "@odata.context": "$metadata#Sales(Customer(Country),
+ "@context": "$metadata#Sales(Customer(Country),
Product(Category(Name)),Total)",
"value": [
{ "Customer": { "Country": "USA", "Name": "Joe" },
"Product": { "Category": { "Name": "Non-Food" }, "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 1 },
+ "Total@type": "Decimal", "Total": 1 },
...
```
plus additional fifteen rollup entities for subtotals: five without customer name
```json
{ "Customer": { "Country": "USA" },
"Product": { "Category": { "Name": "Food" }, "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 2 },
+ "Total@type": "Decimal", "Total": 2 },
...
```
six without product name
```json
{ "Customer": { "Country": "USA", "Name": "Joe" },
"Product": { "Category": { "Name": "Food" } },
- "Total@odata.type": "Decimal", "Total": 6 },
+ "Total@type": "Decimal", "Total": 6 },
...
```
and four with neither customer nor product name
```json
{ "Customer": { "Country": "USA" },
"Product": { "Category": { "Name": "Food" } },
- "Total@odata.type": "Decimal", "Total": 14 },
+ "Total@type": "Decimal", "Total": 14 },
...
]
}
diff --git a/odata-data-aggregation-ext/3.3 Transformations Preserving the Input Set Structure.md b/odata-data-aggregation-ext/3.3 Transformations Preserving the Input Set Structure.md
index 7e65f7e40..82fbdd4f8 100644
--- a/odata-data-aggregation-ext/3.3 Transformations Preserving the Input Set Structure.md
+++ b/odata-data-aggregation-ext/3.3 Transformations Preserving the Input Set Structure.md
@@ -41,7 +41,7 @@ GET /service/Sales?$apply=bottomcount(2,Amount)
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 1, "Amount": 1 },
{ "ID": 7, "Amount": 1 }
@@ -58,7 +58,7 @@ GET /service/Sales?$apply=topcount(2,Amount)
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 3, "Amount": 4 },
{ "ID": 4, "Amount": 8 }
@@ -80,7 +80,7 @@ GET /service/Sales?$apply=bottompercent(50,Amount)
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 1, "Amount": 1 },
{ "ID": 2, "Amount": 2 },
@@ -101,7 +101,7 @@ GET /service/Sales?$apply=toppercent(50,Amount)
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 3, "Amount": 4 },
{ "ID": 4, "Amount": 8 }
@@ -122,7 +122,7 @@ GET /service/Sales?$apply=bottomsum(7,Amount)
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 1, "Amount": 1 },
{ "ID": 2, "Amount": 2 },
@@ -142,7 +142,7 @@ GET /service/Sales?$apply=topsum(15,Amount)
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 3, "Amount": 4 },
{ "ID": 4, "Amount": 8 },
@@ -164,7 +164,7 @@ GET /service/Sales?$apply=filter(Amount gt 3)
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 3, "Amount": 4 },
{ "ID": 4, "Amount": 8 },
@@ -199,14 +199,14 @@ GET /service/Sales?$apply=groupby((Product/Name),
results in
```json
{
- "@odata.context": "$metadata#Sales(Product(Name),Total)",
+ "@context": "$metadata#Sales(Product(Name),Total)",
"value": [
{ "Product": { "Name": "Coffee" },
- "Total@odata.type": "Decimal", "Total": 12 },
+ "Total@type": "Decimal", "Total": 12 },
{ "Product": { "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 8 },
+ "Total@type": "Decimal", "Total": 8 },
{ "Product": { "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 4 }
+ "Total@type": "Decimal", "Total": 4 }
]
}
```
@@ -224,7 +224,7 @@ GET /service/Sales?$apply=search(coffee)
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 3, "Amount": 4 },
{ "ID": 4, "Amount": 8 }
@@ -247,7 +247,7 @@ GET /service/Sales?$apply=orderby(Customer/Name desc)/skip(2)/top(2)
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 6, "Amount": 2 },
{ "ID": 7, "Amount": 1 }
@@ -272,7 +272,7 @@ GET /service/Sales?$apply=orderby(Customer/Name desc)/top(2)
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 4, "Amount": 8 },
{ "ID": 5, "Amount": 4 }
diff --git a/odata-data-aggregation-ext/3.4 Transformations Changing the Input Set Structure.md b/odata-data-aggregation-ext/3.4 Transformations Changing the Input Set Structure.md
index 58debcadd..5fd31523f 100644
--- a/odata-data-aggregation-ext/3.4 Transformations Changing the Input Set Structure.md
+++ b/odata-data-aggregation-ext/3.4 Transformations Changing the Input Set Structure.md
@@ -20,16 +20,16 @@ GET /service/Sales?$apply=compute(Amount mul Product/TaxRate as Tax)
results in
```json
{
- "@odata.context": "$metadata#Sales(*,Tax)",
+ "@context": "$metadata#Sales(*,Tax)",
"value": [
- { "ID": 1, "Amount": 1, "Tax@odata.type": "Decimal", "Tax": 0.14 },
- { "ID": 2, "Amount": 2, "Tax@odata.type": "Decimal", "Tax": 0.12 },
- { "ID": 3, "Amount": 4, "Tax@odata.type": "Decimal", "Tax": 0.24 },
- { "ID": 4, "Amount": 8, "Tax@odata.type": "Decimal", "Tax": 0.48 },
- { "ID": 5, "Amount": 4, "Tax@odata.type": "Decimal", "Tax": 0.56 },
- { "ID": 6, "Amount": 2, "Tax@odata.type": "Decimal", "Tax": 0.12 },
- { "ID": 7, "Amount": 1, "Tax@odata.type": "Decimal", "Tax": 0.14 },
- { "ID": 8, "Amount": 2, "Tax@odata.type": "Decimal", "Tax": 0.28 }
+ { "ID": 1, "Amount": 1, "Tax@type": "Decimal", "Tax": 0.14 },
+ { "ID": 2, "Amount": 2, "Tax@type": "Decimal", "Tax": 0.12 },
+ { "ID": 3, "Amount": 4, "Tax@type": "Decimal", "Tax": 0.24 },
+ { "ID": 4, "Amount": 8, "Tax@type": "Decimal", "Tax": 0.48 },
+ { "ID": 5, "Amount": 4, "Tax@type": "Decimal", "Tax": 0.56 },
+ { "ID": 6, "Amount": 2, "Tax@type": "Decimal", "Tax": 0.12 },
+ { "ID": 7, "Amount": 1, "Tax@type": "Decimal", "Tax": 0.14 },
+ { "ID": 8, "Amount": 2, "Tax@type": "Decimal", "Tax": 0.28 }
]
}
```
@@ -57,45 +57,45 @@ GET /service/Products?$apply=join(Sales as Sale)&$select=ID&$expand=Sale
results in
```json
{
- "@odata.context": "$metadata#Products(ID,Sale())",
+ "@context": "$metadata#Products(ID,Sale())",
"value": [
{ "ID": "P1",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 2, "Amount": 2 } },
{ "ID": "P1",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 6, "Amount": 2 } },
{ "ID": "P2",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 3, "Amount": 4 } },
{ "ID": "P2",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 4, "Amount": 8 } },
{ "ID": "P3",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 1, "Amount": 1 } },
{ "ID": "P3",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 5, "Amount": 4 } },
{ "ID": "P3",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 7, "Amount": 1 } },
{ "ID": "P3",
"Sale": {
- "@odata.context": "#Sales/$entity",
+ "@context": "#Sales/$entity",
"ID": 8, "Amount": 2 } }
]
}
```
-In this example, `$expand=Sale` is used to include the target entities in the result. There are no subsequent transformations like `groupby` that would cause it to be expanded by default. If the first parameter `Sales` was a collection-valued complex property of type `SalesModel.SalesComplexType`, the complex property `Sale` would be in the result regardless, and its context would be `"@odata.context": "#SalesModel.SalesComplexType"`.
+In this example, `$expand=Sale` is used to include the target entities in the result. There are no subsequent transformations like `groupby` that would cause it to be expanded by default. If the first parameter `Sales` was a collection-valued complex property of type `SalesModel.SalesComplexType`, the complex property `Sale` would be in the result regardless, and its context would be `"@context": "#SalesModel.SalesComplexType"`.
Applying `outerjoin` instead would return an additional instance for product with `"ID": "P4"` and `Sale` having a null value.
:::
@@ -114,9 +114,9 @@ GET /service/Sales?$apply=nest(groupby((Customer/ID)) as Customers))
results in
```json
{
- "@odata.context":"$metadata#Sales(Customers())",
+ "@context":"$metadata#Sales(Customers())",
"value": [
- { "Customers@odata.context": "#Sales(Customer(ID))",
+ { "Customers@context": "#Sales(Customer(ID))",
"Customers": [ { "Customer": { "ID": "C1" } },
{ "Customer": { "ID": "C2" } },
{ "Customer": { "ID": "C3" } } ] }
@@ -151,24 +151,24 @@ GET /service/Customers?$apply=addnested(Sales,
results in
```json
{
- "@odata.context": "$metadata#Customers(FilteredSales())",
+ "@context": "$metadata#Customers(FilteredSales())",
"value": [
{ "ID": "C1", "Name": "Joe", "Country": "USA",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": [{ "ID": "3", "Amount": 4 }]},
{ "ID": "C2", "Name": "Sue", "Country": "USA",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": [{ "ID": "4", "Amount": 8 },
{ "ID": "5", "Amount": 4 }]},
{ "ID": "C3", "Name": "Sue", "Country": "Netherlands",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": []},
{ "ID": "C4", "Name": "Luc", "Country": "France",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": []}
]
}
```
-If `Sales` was a collection-valued complex property of type `SalesModel.SalesComplexType`, the context would be `"FilteredSales@odata.context": "#Collection(SalesModel.SalesComplexType)"`.
+If `Sales` was a collection-valued complex property of type `SalesModel.SalesComplexType`, the context would be `"FilteredSales@context": "#Collection(SalesModel.SalesComplexType)"`.
:::
diff --git a/odata-data-aggregation-ext/3.5 Expressions Evaluable on a Collection.md b/odata-data-aggregation-ext/3.5 Expressions Evaluable on a Collection.md
index 2acc32795..93ac51e25 100644
--- a/odata-data-aggregation-ext/3.5 Expressions Evaluable on a Collection.md
+++ b/odata-data-aggregation-ext/3.5 Expressions Evaluable on a Collection.md
@@ -23,7 +23,7 @@ GET /service/Sales?$filter=Amount mul 3 ge $these/aggregate(Amount with sum)
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": "4", "Amount": 8 }
]
@@ -48,7 +48,7 @@ GET /service/Products?$filter=Sales/any(s:s/Amount ge
Both examples result in
```json
{
- "@odata.context": "$metadata#Products",
+ "@context": "$metadata#Products",
"value": [
{ "ID": "P3", "Name": "Paper", "Color": "White", "TaxRate": 0.14 }
]
@@ -68,7 +68,7 @@ GET /service/Sales?$apply=topcount($these/$count div 3,Amount)
results in 2 (a third of 8, rounded down) entities. (This differs from `toppercent(33.3,Amount)`, which returns only the sales entity with `ID` 4, because that already makes up a third of the total amount.)
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": 3, "Amount": 4 },
{ "ID": 4, "Amount": 8 }
@@ -94,7 +94,7 @@ GET /service/Sales?$apply=aggregate(Amount with sum as Total)
results in
```json
{
- "@odata.context": "$metadata#Sales(Total)",
+ "@context": "$metadata#Sales(Total)",
"value": []
}
```
@@ -113,16 +113,16 @@ GET /service/Products
results in
```json
{
- "@odata.context":"$metadata#Products(Sales(Total))",
+ "@context":"$metadata#Products(Sales(Total))",
"value": [
{ "ID": "P2", "Name": "Coffee", "Color": "Brown", "TaxRate": 0.06,
- "Sales": [ { "Total@odata.type": "Decimal", "Total": 12 } ] },
+ "Sales": [ { "Total@type": "Decimal", "Total": 12 } ] },
{ "ID": "P3", "Name": "Paper", "Color": "White", "TaxRate": 0.14,
- "Sales": [ { "Total@odata.type": "Decimal", "Total": 8 } ] },
+ "Sales": [ { "Total@type": "Decimal", "Total": 8 } ] },
{ "ID": "P4", "Name": "Pencil", "Color": "Black", "TaxRate": 0.14,
"Sales": [ { "Total": null } ] },
{ "ID": "P1", "Name": "Sugar", "Color": "White", "TaxRate": 0.06,
- "Sales": [ { "Total@odata.type": "Decimal", "Total": 4 } ] }
+ "Sales": [ { "Total@type": "Decimal", "Total": 4 } ] }
]
}
```
diff --git a/odata-data-aggregation-ext/4 Cross-Joins and Aggregation.md b/odata-data-aggregation-ext/4 Cross-Joins and Aggregation.md
index f4626b187..48b9612c3 100644
--- a/odata-data-aggregation-ext/4 Cross-Joins and Aggregation.md
+++ b/odata-data-aggregation-ext/4 Cross-Joins and Aggregation.md
@@ -18,7 +18,7 @@ GET /service/$crossjoin(Products,Sales)
results in
```json
{
- "@odata.context": "$metadata#Collection(Edm.ComplexType)",
+ "@context": "$metadata#Collection(Edm.ComplexType)",
"value": [
{ "Products": { "Name": "Paper" }, "Sales": { "Amount": 1 } },
{ "Products": { "Name": "Sugar" }, "Sales": { "Amount": 2 } },
@@ -40,17 +40,17 @@ GET /service/$crossjoin(Products,Sales)
results in
```json
{
- "@odata.context": "$metadata#Collection(Edm.ComplexType)",
+ "@context": "$metadata#Collection(Edm.ComplexType)",
"value": [
{ "Products": { "Name": "Coffee" },
- "AggregatedSales@odata.context": "#Sales(Total)",
- "AggregatedSales": { "Total@odata.type": "Decimal", "Total": 12 } },
+ "AggregatedSales@context": "#Sales(Total)",
+ "AggregatedSales": { "Total@type": "Decimal", "Total": 12 } },
{ "Products": { "Name": "Paper" },
- "AggregatedSales@odata.context": "#Sales(Total)",
- "AggregatedSales": { "Total@odata.type": "Decimal", "Total": 8 } },
+ "AggregatedSales@context": "#Sales(Total)",
+ "AggregatedSales": { "Total@type": "Decimal", "Total": 8 } },
{ "Products": { "Name": "Sugar" },
- "AggregatedSales@odata.context": "#Sales(Total)",
- "AggregatedSales": { "Total@odata.type": "Decimal", "Total": 4 } }
+ "AggregatedSales@context": "#Sales(Total)",
+ "AggregatedSales": { "Total@type": "Decimal", "Total": 4 } }
]
}
```
diff --git a/odata-data-aggregation-ext/5 Vocabulary for Data Aggregation.md b/odata-data-aggregation-ext/5 Vocabulary for Data Aggregation.md
index 1da4fc207..80f719f9c 100644
--- a/odata-data-aggregation-ext/5 Vocabulary for Data Aggregation.md
+++ b/odata-data-aggregation-ext/5 Vocabulary for Data Aggregation.md
@@ -262,7 +262,7 @@ GET /service/SalesOrganizations?$filter=Aggregation.isdescendant(
results in
```json
{
- "@odata.context": "$metadata#SalesOrganizations",
+ "@context": "$metadata#SalesOrganizations",
"value": [
{ "ID": "EMEA Central", "Name": "EMEA Central" },
{ "ID": "Sales Netherlands", "Name": "Sales Netherlands" },
@@ -289,7 +289,7 @@ GET /service/SalesOrganizations?$filter=Aggregation.isdescendant(
results in
```json
{
- "@odata.context": "$metadata#SalesOrganizations",
+ "@context": "$metadata#SalesOrganizations",
"value": [
{ "ID": "EMEA Central", "Name": "EMEA Central" },
{ "ID": "EMEA South", "Name": "EMEA South" },
@@ -311,7 +311,7 @@ GET /service/SalesOrganizations?$filter=Aggregation.isleaf(
results in
```json
{
- "@odata.context": "$metadata#SalesOrganizations",
+ "@context": "$metadata#SalesOrganizations",
"value": [
{ "ID": "Sales Office London", "Name": "Sales Office London" },
{ "ID": "Sales Office New York", "Name": "Sales Office New York" },
@@ -333,7 +333,7 @@ GET /service/SalesOrganizations?$filter=Aggregation.isleaf(
results in
```json
{
- "@odata.context": "$metadata#SalesOrganizations(*,Superordinate(ID))",
+ "@context": "$metadata#SalesOrganizations(*,Superordinate(ID))",
"value": [
{ "ID": "Sales Office London", "Name": "Sales Office London",
"Superordinate": { "ID": "EMEA United Kingdom" } },
@@ -358,7 +358,7 @@ GET /service/Sales?$select=ID&$filter=Aggregation.isdescendant(
results in
```json
{
- "@odata.context": "$metadata#Sales(ID)",
+ "@context": "$metadata#Sales(ID)",
"value": [
{ "ID": 6 },
{ "ID": 7 },
diff --git a/odata-data-aggregation-ext/6 Hierarchical Transformations.md b/odata-data-aggregation-ext/6 Hierarchical Transformations.md
index 540920d96..7cd072b9b 100644
--- a/odata-data-aggregation-ext/6 Hierarchical Transformations.md
+++ b/odata-data-aggregation-ext/6 Hierarchical Transformations.md
@@ -110,12 +110,12 @@ GET /service/SalesOrganizations?$apply=
results in
```json
{
- "@odata.context": "$metadata#SalesOrganizations",
+ "@context": "$metadata#SalesOrganizations",
"value": [
{ "ID": "EMEA", "Name": "EMEA",
- "Superordinate": { "@odata.id": "SalesOrganizations('Sales')" } },
+ "Superordinate": { "@id": "SalesOrganizations('Sales')" } },
{ "ID": "US", "Name": "US",
- "Superordinate": { "@odata.id": "SalesOrganizations('Sales')" } },
+ "Superordinate": { "@id": "SalesOrganizations('Sales')" } },
{ "ID": "Sales", "Name": "Sales",
"Superordinate": null }
]
@@ -134,14 +134,14 @@ GET /service/SalesOrganizations?$apply=
results in
```json
{
- "@odata.context": "$metadata#SalesOrganizations",
+ "@context": "$metadata#SalesOrganizations",
"value": [
{ "ID": "US West", "Name": "US West",
- "Superordinate": { "@odata.id": "SalesOrganizations('US')" } },
+ "Superordinate": { "@id": "SalesOrganizations('US')" } },
{ "ID": "US", "Name": "US",
- "Superordinate": { "@odata.id": "SalesOrganizations('Sales')" } },
+ "Superordinate": { "@id": "SalesOrganizations('Sales')" } },
{ "ID": "US East", "Name": "US East",
- "Superordinate": { "@odata.id": "SalesOrganizations('US')" } }
+ "Superordinate": { "@id": "SalesOrganizations('US')" } }
]
}
```
@@ -161,7 +161,7 @@ GET /service/Sales?$apply=
results in
```json
{
- "@odata.context": "$metadata#Sales",
+ "@context": "$metadata#Sales",
"value": [
{ "ID": "4", "Amount": 8,
"SalesOrganization": { "ID": "US East", "Name": "US East" } },
@@ -263,12 +263,12 @@ GET /service/SalesOrganizations?$apply=
results in
```json
{
- "@odata.context": "$metadata#SalesOrganizations",
+ "@context": "$metadata#SalesOrganizations",
"value": [
{ "ID": "US", "Name": "US",
- "Superordinate": { "@odata.id": "SalesOrganizations('Sales')" } },
+ "Superordinate": { "@id": "SalesOrganizations('Sales')" } },
{ "ID": "US East", "Name": "US East",
- "Superordinate": { "@odata.id": "SalesOrganizations('US')" } }
+ "Superordinate": { "@id": "SalesOrganizations('US')" } }
]
}
```
@@ -374,7 +374,7 @@ GET /service/SalesOrganizations?$apply=
results in
```json
{
- "@odata.context":
+ "@context":
"$metadata#SalesOrganizations(ID,Name,SubOrgCnt,Superordinate(ID))",
"value": [
{ "ID": "US West", "Name": "US West",
@@ -415,18 +415,18 @@ GET /service/Sales?$apply=groupby(
results in
```json
{
- "@odata.context": "$metadata#Sales(SalesOrganization(),
+ "@context": "$metadata#Sales(SalesOrganization(),
TotalAmountIncl,TotalAmountExcl)",
"value": [
{ "SalesOrganization": { "ID": "US West", "Name": "US West" },
- "TotalAmountIncl@odata.type": "Decimal", "TotalAmountIncl": 7,
- "TotalAmountExcl@odata.type": "Decimal" ,"TotalAmountExcl": 7 },
+ "TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 7,
+ "TotalAmountExcl@type": "Decimal" ,"TotalAmountExcl": 7 },
{ "SalesOrganization": { "ID": "US", "Name": "US" },
- "TotalAmountIncl@odata.type": "Decimal", "TotalAmountIncl": 19,
+ "TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 19,
"TotalAmountExcl": null },
{ "SalesOrganization": { "ID": "US East", "Name": "US East" },
- "TotalAmountIncl@odata.type": "Decimal", "TotalAmountIncl": 12,
- "TotalAmountExcl@odata.type": "Decimal", "TotalAmountExcl": 12 }
+ "TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 12,
+ "TotalAmountExcl@type": "Decimal", "TotalAmountExcl": 12 }
]
}
```
@@ -443,7 +443,7 @@ GET /service/Sales?$apply=
results in
```json
{
- "@odata.context": "$metadata#Sales(SalesOrganization(),TotalAmount)",
+ "@context": "$metadata#Sales(SalesOrganization(),TotalAmount)",
"value": [
{ "SalesOrganization": { "ID": "Sales", "Name": "Corporate Sales" },
"TotalAmount": null },
diff --git a/odata-data-aggregation-ext/7 Examples.md b/odata-data-aggregation-ext/7 Examples.md
index cb2a3c5ac..25e4db50e 100644
--- a/odata-data-aggregation-ext/7 Examples.md
+++ b/odata-data-aggregation-ext/7 Examples.md
@@ -16,7 +16,7 @@ GET /service/Customers?$apply=groupby((Name))
results in
```json
{
- "@odata.context": "$metadata#Customers(Name)",
+ "@context": "$metadata#Customers(Name)",
"value": [
{ "Name": "Luc" },
{ "Name": "Joe" },
@@ -38,7 +38,7 @@ GET /service/Sales?$apply=groupby((Customer/Name))
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Name))",
+ "@context": "$metadata#Sales(Customer(Name))",
"value": [
{ "Customer": { "Name": "Joe" } },
{ "Customer": { "Name": "Sue" } }
@@ -61,7 +61,7 @@ GET /service/Sales?$apply=groupby((Customer/Name,Customer/ID))
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Name,ID))",
+ "@context": "$metadata#Sales(Customer(Name,ID))",
"value": [
{ "Customer": { "Name": "Joe", "ID": "C1" } },
{ "Customer": { "Name": "Sue", "ID": "C2" } },
@@ -85,7 +85,7 @@ GET /service/Sales?$apply=groupby((Customer))
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer())",
+ "@context": "$metadata#Sales(Customer())",
"value": [
{ "Customer": { "ID": "C1", "Name": "Joe", "Country": "USA" } },
{ "Customer": { "ID": "C2", "Name": "Sue", "Country": "USA" } },
@@ -103,7 +103,7 @@ GET /service/Sales?$apply=groupby((Customer/Name,Customer/ID,Product/Name))
and results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Name,ID),Product(Name))",
+ "@context": "$metadata#Sales(Customer(Name,ID),Product(Name))",
"value": [
{ "Customer": { "Name": "Joe", "ID": "C1" },
"Product": { "Name": "Coffee"} },
@@ -133,13 +133,13 @@ GET /service/Products?$apply=groupby((SalesModel.FoodProduct/Rating,
results in
```json
{
- "@odata.context": "$metadata#Products(SalesModel.FoodProduct/Rating,
+ "@context": "$metadata#Products(SalesModel.FoodProduct/Rating,
SalesModel.NonFoodProduct/RatingClass)",
"value": [
- { "@odata.type": "#SalesModel.FoodProduct", "Rating": 5 },
- { "@odata.type": "#SalesModel.FoodProduct", "Rating": null },
- { "@odata.type": "#SalesModel.NonFoodProduct", "RatingClass": "average" },
- { "@odata.type": "#SalesModel.NonFoodProduct", "RatingClass": null }
+ { "@type": "#SalesModel.FoodProduct", "Rating": 5 },
+ { "@type": "#SalesModel.FoodProduct", "Rating": null },
+ { "@type": "#SalesModel.NonFoodProduct", "RatingClass": "average" },
+ { "@type": "#SalesModel.NonFoodProduct", "RatingClass": null }
]
}
```
@@ -153,10 +153,10 @@ GET /service/Products?$apply=groupby((SalesModel.FoodProduct/Rating))
results in a third group representing entities with no `SalesModel.FoodProduct/Rating`, including the `SalesModel.NonFoodProduct`s:
```json
{
- "@odata.context": "$metadata#Products(@Core.AnyStructure)",
+ "@context": "$metadata#Products(@Core.AnyStructure)",
"value": [
- { "@odata.type": "#SalesModel.FoodProduct", "Rating": 5 },
- { "@odata.type": "#SalesModel.FoodProduct", "Rating": null },
+ { "@type": "#SalesModel.FoodProduct", "Rating": 5 },
+ { "@type": "#SalesModel.FoodProduct", "Rating": null },
{ }
]
}
@@ -176,12 +176,12 @@ GET /service/Products?$apply=groupby((Name),
results in
```json
{
- "@odata.context": "$metadata#Products(Name,Total)",
+ "@context": "$metadata#Products(Name,Total)",
"value": [
- { "Name": "Coffee", "Total@odata.type": "Decimal", "Total": 12 },
- { "Name": "Paper", "Total@odata.type": "Decimal", "Total": 8 },
+ { "Name": "Coffee", "Total@type": "Decimal", "Total": 12 },
+ { "Name": "Paper", "Total@type": "Decimal", "Total": 8 },
{ "Name": "Pencil", "Total": null },
- { "Name": "Sugar", "Total@odata.type": "Decimal", "Total": 4 }
+ { "Name": "Sugar", "Total@type": "Decimal", "Total": 4 }
]
}
```
@@ -198,20 +198,20 @@ GET /service/Products?$apply=addnested(Sales,
results in
```json
{
- "@odata.context": "$metadata#Products(AggregatedSales())",
+ "@context": "$metadata#Products(AggregatedSales())",
"value": [
{ "ID": "P2", "Name": "Coffee", "Color": "Brown", "TaxRate": 0.06,
- "AggregatedSales@odata.context": "#Sales(Total)",
- "AggregatedSales": [ { "Total@odata.type": "Decimal", "Total": 12 } ] },
+ "AggregatedSales@context": "#Sales(Total)",
+ "AggregatedSales": [ { "Total@type": "Decimal", "Total": 12 } ] },
{ "ID": "P3", "Name": "Paper", "Color": "White", "TaxRate": 0.14,
- "AggregatedSales@odata.context": "#Sales(Total)",
- "AggregatedSales": [ { "Total@odata.type": "Decimal", "Total": 8 } ] },
+ "AggregatedSales@context": "#Sales(Total)",
+ "AggregatedSales": [ { "Total@type": "Decimal", "Total": 8 } ] },
{ "ID": "P4", "Name": "Pencil", "Color": "Black", "TaxRate": 0.14,
- "AggregatedSales@odata.context": "#Sales(Total)",
+ "AggregatedSales@context": "#Sales(Total)",
"AggregatedSales": [ { "Total": null } ] },
{ "ID": "P1", "Name": "Sugar", "Color": "White", "TaxRate": 0.06,
- "AggregatedSales@odata.context": "#Sales(Total)",
- "AggregatedSales": [ { "Total@odata.type": "Decimal", "Total": 4 } ] }
+ "AggregatedSales@context": "#Sales(Total)",
+ "AggregatedSales": [ { "Total@type": "Decimal", "Total": 4 } ] }
]
}
```
@@ -225,16 +225,16 @@ GET /service/Products?$compute=Sales/aggregate(Amount with sum) as Total
results in
```json
{
- "@odata.context": "$metadata#Products(*,Total)",
+ "@context": "$metadata#Products(*,Total)",
"value": [
{ "ID": "P2", "Name": "Coffee", "Color": "Brown", "TaxRate": 0.06,
- "Total@odata.type": "Decimal", "Total": 12 },
+ "Total@type": "Decimal", "Total": 12 },
{ "ID": "P3", "Name": "Paper", "Color": "White", "TaxRate": 0.14,
- "Total@odata.type": "Decimal", "Total": 8 },
+ "Total@type": "Decimal", "Total": 8 },
{ "ID": "P4", "Name": "Pencil", "Color": "Black", "TaxRate": 0.14,
"Total": null },
{ "ID": "P1", "Name": "Sugar", "Color": "White", "TaxRate": 0.06,
- "Total@odata.type": "Decimal", "Total": 4 }
+ "Total@type": "Decimal", "Total": 4 }
]
}
```
@@ -252,17 +252,17 @@ GET /service/Products?$apply=
results in
```json
{
- "@odata.context": "$metadata#Products(Name,TotalSales())",
+ "@context": "$metadata#Products(Name,TotalSales())",
"value": [
{ "Name": "Coffee",
- "TotalSales@odata.context": "#Sales(Total)/$entity",
- "TotalSales": { "Total@odata.type": "Decimal", "Total": 12 } },
+ "TotalSales@context": "#Sales(Total)/$entity",
+ "TotalSales": { "Total@type": "Decimal", "Total": 12 } },
{ "Name": "Paper",
- "TotalSales@odata.context": "#Sales(Total)/$entity",
- "TotalSales": { "Total@odata.type": "Decimal", "Total": 8 } },
+ "TotalSales@context": "#Sales(Total)/$entity",
+ "TotalSales": { "Total@type": "Decimal", "Total": 8 } },
{ "Name": "Sugar",
- "TotalSales@odata.context": "#Sales(Total)/$entity",
- "TotalSales": { "Total@odata.type": "Decimal", "Total": 4 } }
+ "TotalSales@context": "#Sales(Total)/$entity",
+ "TotalSales": { "Total@type": "Decimal", "Total": 4 } }
]
}
```
@@ -279,7 +279,7 @@ GET /service/Sales?$apply=groupby((Customer/Country),
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Country),AverageAmount)",
+ "@context": "$metadata#Sales(Customer(Country),AverageAmount)",
"value": [
{ "Customer": { "Country": "Netherlands" },
"AverageAmount": 1.6666666666666667 },
@@ -300,12 +300,12 @@ GET /service/Products?$apply=groupby((Name),
results in
```json
{
- "@odata.context": "$metadata#Products(Name,SalesCount)",
+ "@context": "$metadata#Products(Name,SalesCount)",
"value": [
- { "Name": "Coffee", "SalesCount@odata.type": "Decimal", "SalesCount": 2 },
- { "Name": "Paper", "SalesCount@odata.type": "Decimal", "SalesCount": 4 },
- { "Name": "Pencil", "SalesCount@odata.type": "Decimal", "SalesCount": 0 },
- { "Name": "Sugar", "SalesCount@odata.type": "Decimal", "SalesCount": 2 }
+ { "Name": "Coffee", "SalesCount@type": "Decimal", "SalesCount": 2 },
+ { "Name": "Paper", "SalesCount@type": "Decimal", "SalesCount": 4 },
+ { "Name": "Pencil", "SalesCount@type": "Decimal", "SalesCount": 0 },
+ { "Name": "Sugar", "SalesCount@type": "Decimal", "SalesCount": 2 }
]
}
```
@@ -323,23 +323,23 @@ GET /service/Products?$apply=groupby((Name),addnested(Sales,
results in
```json
{
- "@odata.context": "$metadata#Products(Name,AggregatedSales())",
+ "@context": "$metadata#Products(Name,AggregatedSales())",
"value": [
{ "Name": "Coffee",
- "AggregatedSales@odata.context": "#Sales(SalesCount,TotalAmount)",
+ "AggregatedSales@context": "#Sales(SalesCount,TotalAmount)",
"AggregatedSales": [ { "SalesCount": 2,
- "TotalAmount@odata.type": "Decimal", "TotalAmount": 12 } ] },
+ "TotalAmount@type": "Decimal", "TotalAmount": 12 } ] },
{ "Name": "Paper",
- "AggregatedSales@odata.context": "#Sales(SalesCount,TotalAmount)",
+ "AggregatedSales@context": "#Sales(SalesCount,TotalAmount)",
"AggregatedSales": [ { "SalesCount": 4,
- "TotalAmount@odata.type": "Decimal", "TotalAmount": 8 } ] },
+ "TotalAmount@type": "Decimal", "TotalAmount": 8 } ] },
{ "Name": "Pencil",
- "AggregatedSales@odata.context": "#Sales(SalesCount,TotalAmount)",
+ "AggregatedSales@context": "#Sales(SalesCount,TotalAmount)",
"AggregatedSales": [ { "SalesCount": 0, "TotalAmount": null } ] },
{ "Name": "Sugar",
- "AggregatedSales@odata.context": "#Sales(SalesCount,TotalAmount)",
+ "AggregatedSales@context": "#Sales(SalesCount,TotalAmount)",
"AggregatedSales": [ { "SalesCount": 2,
- "TotalAmount@odata.type": "Decimal", "TotalAmount": 4 } ] }
+ "TotalAmount@type": "Decimal", "TotalAmount": 4 } ] }
]
}
```
@@ -355,7 +355,7 @@ GET /service/Products?$filter=Sales/aggregate(Amount with sum) ge 10
results in
```json
{
- "@odata.context": "$metadata#Products",
+ "@context": "$metadata#Products",
"value": [
{ "ID": "P2", "Name": "Coffee", "Color": "Brown", "TaxRate": 0.06 },
{ "ID": "P3", "Name": "Paper", "Color": "White", "TaxRate": 0.14 }
@@ -372,7 +372,7 @@ GET /service/Customers?$orderby=Sales/aggregate(Amount with sum) desc
results in
```json
{
- "@odata.context": "$metadata#Customers",
+ "@context": "$metadata#Customers",
"value": [
{ "ID": "C2", "Name": "Sue", "Country": "USA" },
{ "ID": "C1", "Name": "Joe", "Country": "USA" },
@@ -392,23 +392,23 @@ GET /service/Sales?$compute=Amount divby $these/aggregate(Amount with sum)
results in
```json
{
- "@odata.context": "$metadata#Sales(*,Contribution)",
+ "@context": "$metadata#Sales(*,Contribution)",
"value": [
- { "ID": 1, "Amount": 1, "Contribution@odata.type": "Decimal",
+ { "ID": 1, "Amount": 1, "Contribution@type": "Decimal",
"Contribution": 0.0416666666666667 },
- { "ID": 2, "Amount": 2, "Contribution@odata.type": "Decimal",
+ { "ID": 2, "Amount": 2, "Contribution@type": "Decimal",
"Contribution": 0.0833333333333333 },
- { "ID": 3, "Amount": 4, "Contribution@odata.type": "Decimal",
+ { "ID": 3, "Amount": 4, "Contribution@type": "Decimal",
"Contribution": 0.1666666666666667 },
- { "ID": 4, "Amount": 8, "Contribution@odata.type": "Decimal",
+ { "ID": 4, "Amount": 8, "Contribution@type": "Decimal",
"Contribution": 0.3333333333333333 },
- { "ID": 5, "Amount": 4, "Contribution@odata.type": "Decimal",
+ { "ID": 5, "Amount": 4, "Contribution@type": "Decimal",
"Contribution": 0.1666666666666667 },
- { "ID": 6, "Amount": 2, "Contribution@odata.type": "Decimal",
+ { "ID": 6, "Amount": 2, "Contribution@type": "Decimal",
"Contribution": 0.0833333333333333 },
- { "ID": 7, "Amount": 1, "Contribution@odata.type": "Decimal",
+ { "ID": 7, "Amount": 1, "Contribution@type": "Decimal",
"Contribution": 0.0416666666666667 },
- { "ID": 8, "Amount": 2, "Contribution@odata.type": "Decimal",
+ { "ID": 8, "Amount": 2, "Contribution@type": "Decimal",
"Contribution": 0.0833333333333333 }
]
}
@@ -424,7 +424,7 @@ GET /service/Categories?$filter=Products/any(
results in
```json
{
- "@odata.context": "$metadata#Categories",
+ "@context": "$metadata#Categories",
"value": [
{ "ID": "PG1", "Name": "Food" }
]
@@ -446,14 +446,14 @@ GET /service/Sales?$apply=
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(),CustomerAmount,Contribution)",
+ "@context": "$metadata#Sales(Customer(),CustomerAmount,Contribution)",
"value": [
- { "Customer": { "@odata.id": "Customers('C1')" },
- "Contribution@odata.type": "Decimal", "Contribution": 0.2916667 },
- { "Customer": { "@odata.id": "Customers('C2')" },
- "Contribution@odata.type": "Decimal", "Contribution": 0.5 },
- { "Customer": { "@odata.id": "Customers('C3')" },
- "Contribution@odata.type": "Decimal", "Contribution": 0.2083333 }
+ { "Customer": { "@id": "Customers('C1')" },
+ "Contribution@type": "Decimal", "Contribution": 0.2916667 },
+ { "Customer": { "@id": "Customers('C2')" },
+ "Contribution@type": "Decimal", "Contribution": 0.5 },
+ { "Customer": { "@id": "Customers('C3')" },
+ "Contribution@type": "Decimal", "Contribution": 0.2083333 }
]
}
```
@@ -497,18 +497,18 @@ GET /service/Customers?$apply=
results in
```json
{
- "@odata.context": "$metadata#Customers(
+ "@context": "$metadata#Customers(
Addresses(AugmentedSalesOrganization())",
"value": [
{ "ID": "C1", "Name": "Joe", "Country": "US",
"Addresses": [
{ "Locality": "Seattle",
"AugmentedSalesOrganization":
- { "@odata.context": "#SalesOrganizations/$entity",
+ { "@context": "#SalesOrganizations/$entity",
"ID": "US West", "SalesRegion": "US" } },
{ "Locality": "DC",
"AugmentedSalesOrganization":
- { "@odata.context": "#SalesOrganizations/$entity",
+ { "@context": "#SalesOrganizations/$entity",
"ID": "US", "SalesRegion": "Corporate Sales" } },
]
}, ...
@@ -530,28 +530,28 @@ GET /service/Categories?$apply=
results in
```json
{
- "@odata.context": "$metadata#Categories(FilteredProducts()",
+ "@context": "$metadata#Categories(FilteredProducts()",
"value": [
{ "ID": "PG1", "Name": "Food",
- "FilteredProducts@odata.context": "#Products(FilteredSales())",
+ "FilteredProducts@context": "#Products(FilteredSales())",
"FilteredProducts": [
{ "ID": "P1", "Name": "Sugar", "Color": "White",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": [] },
{ "ID": "P2", "Name": "Coffee", "Color": "Brown",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": [ { "ID": 3, "Amount": 4 },
{ "ID": 4, "Amount": 8 } ] }
]
},
{ "ID": "PG2", "Name": "Non-Food",
- "FilteredProducts@odata.context": "#Products(FilteredSales())",
+ "FilteredProducts@context": "#Products(FilteredSales())",
"FilteredProducts": [
{ "ID": "P3", "Name": "Paper", "Color": "White",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": [ { "ID": 5, "Amount": 4 } ] },
{ "ID": "P4", "Name": "Pencil", "Color": "Black",
- "FilteredSales@odata.context": "#Sales",
+ "FilteredSales@context": "#Sales",
"FilteredSales": [] }
]
}
@@ -580,29 +580,29 @@ GET /service/Customers?$apply=addnested(Sales,
results in
```json
{
- "@odata.context": "$metadata#Customers(GroupedSales())",
+ "@context": "$metadata#Customers(GroupedSales())",
"value": [
{ "ID": "C1", "Name": "Joe", "Country": "USA",
- "GroupedSales@odata.context": "#Sales(@Core.AnyStructure)",
+ "GroupedSales@context": "#Sales(@Core.AnyStructure)",
"GroupedSales": [
{ },
{ },
{ }
] },
{ "ID": "C2", "Name": "Sue", "Country": "USA",
- "GroupedSales@odata.context": "#Sales(@Core.AnyStructure)",
+ "GroupedSales@context": "#Sales(@Core.AnyStructure)",
"GroupedSales": [
{ },
{ }
] },
{ "ID": "C3", "Name": "Joe", "Country": "Netherlands",
- "GroupedSales@odata.context": "#Sales(@Core.AnyStructure)",
+ "GroupedSales@context": "#Sales(@Core.AnyStructure)",
"GroupedSales": [
{ },
{ }
] },
{ "ID": "C4", "Name": "Luc", "Country": "France",
- "GroupedSales@odata.context": "#Sales(@Core.AnyStructure)",
+ "GroupedSales@context": "#Sales(@Core.AnyStructure)",
"GroupedSales": [ ] }
]
}
@@ -618,22 +618,22 @@ GET /service/Customers?$apply=outerjoin(Sales as ProductSales)
returns the different combinations of products sold per country:
```json
{
- "@odata.context":"$metadata#Customers(Country,ProductSales())",
+ "@context":"$metadata#Customers(Country,ProductSales())",
"value": [
{ "Country": "Netherlands",
- "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
+ "ProductSales@context": "#Sales(Product(Name))/$entity",
"ProductSales": { "Product": { "Name": "Paper" } } },
{ "Country": "Netherlands",
- "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
+ "ProductSales@context": "#Sales(Product(Name))/$entity",
"ProductSales": { "Product": { "Name": "Sugar" } } },
{ "Country": "USA",
- "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
+ "ProductSales@context": "#Sales(Product(Name))/$entity",
"ProductSales": { "Product": { "Name": "Coffee" } } },
{ "Country": "USA",
- "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
+ "ProductSales@context": "#Sales(Product(Name))/$entity",
"ProductSales": { "Product": { "Name": "Paper" } } },
{ "Country": "USA",
- "ProductSales@odata.context": "#Sales(Product(Name))/$entity",
+ "ProductSales@context": "#Sales(Product(Name))/$entity",
"ProductSales": { "Product": { "Name": "Sugar" } } },
{ "Country": "France", "ProductSales": null }
]
@@ -655,14 +655,14 @@ GET /service/Sales?$apply=groupby((Customer/Country),
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Country),Actual,Forecast)",
+ "@context": "$metadata#Sales(Customer(Country),Actual,Forecast)",
"value": [
{ "Customer": { "Country": "Netherlands" },
- "Actual@odata.type": "Decimal", "Actual": 5,
- "Forecast@odata.type": "Decimal", "Forecast": 4 },
+ "Actual@type": "Decimal", "Actual": 5,
+ "Forecast@type": "Decimal", "Forecast": 4 },
{ "Customer": { "Country": "USA" },
- "Actual@odata.type": "Decimal", "Actual": 19,
- "Forecast@odata.type": "Decimal", "Forecast": 21 }
+ "Actual@type": "Decimal", "Actual": 19,
+ "Forecast@type": "Decimal", "Forecast": 21 }
]
}
```
@@ -678,7 +678,7 @@ GET /service/Sales?$apply=groupby((Customer/Country),aggregate(Amount))
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Country),Amount)",
+ "@context": "$metadata#Sales(Customer(Country),Amount)",
"value": [
{ "Customer": { "Country": "Netherlands" }, "Amount": 5 },
{ "Customer": { "Country": "USA" }, "Amount": 19 }
@@ -745,14 +745,14 @@ GET /service/Sales?$apply=groupby((Customer/Country),
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Country),Total,AvgAmt)",
+ "@context": "$metadata#Sales(Customer(Country),Total,AvgAmt)",
"value": [
{ "Customer": { "Country": "Netherlands" },
- "Total@odata.type": "Decimal", "Total": 5,
- "AvgAmt@odata.type": "Decimal", "AvgAmt": 1.6666667 },
+ "Total@type": "Decimal", "Total": 5,
+ "AvgAmt@type": "Decimal", "AvgAmt": 1.6666667 },
{ "Customer": { "Country": "USA" },
- "Total@odata.type": "Decimal", "Total": 19,
- "AvgAmt@odata.type": "Decimal", "AvgAmt": 3.8 }
+ "Total@type": "Decimal", "Total": 19,
+ "AvgAmt@type": "Decimal", "AvgAmt": 3.8 }
]
}
```
@@ -772,22 +772,22 @@ GET /service/Products?$apply=groupby((Name),
results in
```json
{
- "@odata.context": "$metadata#Products(Name,Total,AggregatedSales())",
+ "@context": "$metadata#Products(Name,Total,AggregatedSales())",
"value": [
{ "Name": "Coffee", "Total": 12,
- "AggregatedSales@odata.context": "#Sales(AvgAmt)",
- "AggregatedSales": [ { "AvgAmt@odata.type": "Decimal",
+ "AggregatedSales@context": "#Sales(AvgAmt)",
+ "AggregatedSales": [ { "AvgAmt@type": "Decimal",
"AvgAmt": 6 } ] },
{ "Name": "Paper", "Total": 8,
- "AggregatedSales@odata.context": "#Sales(AvgAmt)",
- "AggregatedSales": [ { "AvgAmt@odata.type": "Decimal",
+ "AggregatedSales@context": "#Sales(AvgAmt)",
+ "AggregatedSales": [ { "AvgAmt@type": "Decimal",
"AvgAmt": 2 } ] },
{ "Name": "Pencil", "Total": null,
- "AggregatedSales@odata.context": "#Sales(AvgAmt)",
+ "AggregatedSales@context": "#Sales(AvgAmt)",
"AggregatedSales": [ { "AvgAmt": null } ] },
{ "Name": "Sugar", "Total": 4,
- "AggregatedSales@odata.context": "#Sales(AvgAmt)",
- "AggregatedSales": [ { "AvgAmt@odata.type": "Decimal",
+ "AggregatedSales@context": "#Sales(AvgAmt)",
+ "AggregatedSales": [ { "AvgAmt@type": "Decimal",
"AvgAmt": 2 } ] }
]
}
@@ -804,12 +804,12 @@ GET /service/Sales?$apply=groupby((Amount),aggregate(Amount with sum as Total))
will return all distinct amounts appearing in sales orders and how much money was made with deals of this amount
```json
{
- "@odata.context": "$metadata#Sales(Amount,Total)",
+ "@context": "$metadata#Sales(Amount,Total)",
"value": [
- { "Amount": 1, "Total@odata.type": "Decimal", "Total": 2 },
- { "Amount": 2, "Total@odata.type": "Decimal", "Total": 6 },
- { "Amount": 4, "Total@odata.type": "Decimal", "Total": 8 },
- { "Amount": 8, "Total@odata.type": "Decimal", "Total": 8 }
+ { "Amount": 1, "Total@type": "Decimal", "Total": 2 },
+ { "Amount": 2, "Total@type": "Decimal", "Total": 6 },
+ { "Amount": 4, "Total@type": "Decimal", "Total": 8 },
+ { "Amount": 8, "Total@type": "Decimal", "Total": 8 }
]
}
```
@@ -832,19 +832,19 @@ GET /service/Sales?$apply=concat(
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Country),Total)",
+ "@context": "$metadata#Sales(Customer(Country),Total)",
"value": [
{ "Customer":{ "Country": "USA" }, "Product":{ "Name": "Coffee" },
- "Total@odata.type": "Decimal", "Total": 12
+ "Total@type": "Decimal", "Total": 12
},
{ "Customer":{ "Country": "Netherlands" }, "Product":{ "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 3
+ "Total@type": "Decimal", "Total": 3
},
{ "Customer":{ "Country": "USA" },
- "Total@odata.type": "Decimal", "Total": 19
+ "Total@type": "Decimal", "Total": 19
},
{ "Customer":{ "Country": "Netherlands" },
- "Total@odata.type": "Decimal", "Total": 5
+ "Total@type": "Decimal", "Total": 5
}
]
}
@@ -860,22 +860,22 @@ GET /service/Sales?$apply=groupby((Customer/Country,Product/Name),
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Country),Product(Name),Total)",
+ "@context": "$metadata#Sales(Customer(Country),Product(Name),Total)",
"value": [
{ "Customer":{ "Country": "Netherlands" }, "Product":{ "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 3
+ "Total@type": "Decimal", "Total": 3
},
{ "Customer":{ "Country": "Netherlands" }, "Product":{ "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 2
+ "Total@type": "Decimal", "Total": 2
},
{ "Customer":{ "Country": "USA" }, "Product":{ "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 2
+ "Total@type": "Decimal", "Total": 2
},
{ "Customer":{ "Country": "USA" }, "Product":{ "Name": "Coffee" },
- "Total@odata.type": "Decimal", "Total": 12
+ "Total@type": "Decimal", "Total": 12
},
{ "Customer":{ "Country": "USA" }, "Product":{ "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 5
+ "Total@type": "Decimal", "Total": 5
}
]
}
@@ -893,7 +893,7 @@ GET /service/Sales?$apply=concat(
In the result, `Sales` entities 4 and 6 occur twice each with contradictory values of the dynamic property `per`. If a UI consuming the response presents the two groupings in separate columns based on the `per` property, no contradiction effectively arises.
```json
{
- "@odata.context": "$metadata#Sales(*,per,Customer(ID),Product(ID))",
+ "@context": "$metadata#Sales(*,per,Customer(ID),Product(ID))",
"value": [
{ "Customer": { "ID": "C1" }, "Product": { "ID": "P2" },
"ID": "3", "Amount": 4, "per": "Customer" },
@@ -939,18 +939,18 @@ GET /service/Sales?$apply=
results in
```json
{
- "@odata.context": "$metadata#Sales(Customer(Country),Total)",
+ "@context": "$metadata#Sales(Customer(Country),Total)",
"value": [
{ "Customer": { "Country": "Netherlands" },
"Product": { "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 3 },
+ "Total@type": "Decimal", "Total": 3 },
{ "Customer": { "Country": "Netherlands" },
- "Total@odata.type": "Decimal", "Total": 2 },
+ "Total@type": "Decimal", "Total": 2 },
{ "Customer": { "Country": "USA" },
"Product": { "Name": "Coffee" },
- "Total@odata.type": "Decimal", "Total": 12 },
+ "Total@type": "Decimal", "Total": 12 },
{ "Customer": { "Country": "USA" },
- "Total@odata.type": "Decimal", "Total": 7 }
+ "Total@type": "Decimal", "Total": 7 }
]
}
```
@@ -998,24 +998,24 @@ GET /service/Sales?$apply=concat(
results in
```json
{
- "@odata.context": "$metadata#Sales(CustomerCountryAverage)",
+ "@context": "$metadata#Sales(CustomerCountryAverage)",
"value": [
{ "Customer": { "Country": "USA", "ID": "C1" },
- "CustomerCountryAverage@odata.type":"Decimal",
+ "CustomerCountryAverage@type":"Decimal",
"CustomerCountryAverage": 7 },
{ "Customer": { "Country": "USA", "ID": "C2" },
- "CustomerCountryAverage@odata.type":"Decimal",
+ "CustomerCountryAverage@type":"Decimal",
"CustomerCountryAverage": 12 },
{ "Customer": { "Country": "USA" },
- "CustomerCountryAverage@odata.type":"Decimal",
+ "CustomerCountryAverage@type":"Decimal",
"CustomerCountryAverage": 9.5 },
{ "Customer": { "Country": "Netherlands", "ID": "C3" },
- "CustomerCountryAverage@odata.type":"Decimal",
+ "CustomerCountryAverage@type":"Decimal",
"CustomerCountryAverage": 5 },
{ "Customer": { "Country": "Netherlands" },
- "CustomerCountryAverage@odata.type":"Decimal",
+ "CustomerCountryAverage@type":"Decimal",
"CustomerCountryAverage": 5 },
- { "CustomerCountryAverage@odata.type":"Decimal",
+ { "CustomerCountryAverage@type":"Decimal",
"CustomerCountryAverage": 7.25 }
]
}
@@ -1044,17 +1044,17 @@ GET /service/Sales?$apply=
results in
```json
{
- "@odata.context": "$metadata#Sales(TotalAmount,SalesOrganization())",
+ "@context": "$metadata#Sales(TotalAmount,SalesOrganization())",
"value": [
- { "TotalAmount@odata.type": "Decimal", "TotalAmount": 19,
+ { "TotalAmount@type": "Decimal", "TotalAmount": 19,
"SalesOrganization": { "ID": "US", "Name": "US",
- "Superordinate": { "@odata.id": "SalesOrganizations('Sales')" } } },
- { "TotalAmount@odata.type": "Decimal", "TotalAmount": 12,
+ "Superordinate": { "@id": "SalesOrganizations('Sales')" } } },
+ { "TotalAmount@type": "Decimal", "TotalAmount": 12,
"SalesOrganization": { "ID": "US East", "Name": "US East",
- "Superordinate": { "@odata.id": "SalesOrganizations('US')" } } },
- { "TotalAmount@odata.type": "Decimal", "TotalAmount": 7,
+ "Superordinate": { "@id": "SalesOrganizations('US')" } } },
+ { "TotalAmount@type": "Decimal", "TotalAmount": 7,
"SalesOrganization": { "ID": "US West", "Name": "US West",
- "Superordinate": { "@odata.id": "SalesOrganizations('US')" } } }
+ "Superordinate": { "@id": "SalesOrganizations('US')" } } }
]
}
```
@@ -1077,24 +1077,24 @@ GET /service/Sales?$apply=
results in
```json
{
- "@odata.context": "$metadata#Sales(PaperSalesCount,SalesOrganization())",
+ "@context": "$metadata#Sales(PaperSalesCount,SalesOrganization())",
"value": [
- { "PaperSalesCount@odata.type": "Decimal", "PaperSalesCount": 2,
+ { "PaperSalesCount@type": "Decimal", "PaperSalesCount": 2,
"SalesOrganization": { "ID": "US", "Name": "US",
- "Superordinate": { "@odata.id": "SalesOrganizations('Sales')" } } },
- { "PaperSalesCount@odata.type": "Decimal", "PaperSalesCount": 1,
+ "Superordinate": { "@id": "SalesOrganizations('Sales')" } } },
+ { "PaperSalesCount@type": "Decimal", "PaperSalesCount": 1,
"SalesOrganization": { "ID": "US East", "Name": "US East",
- "Superordinate": { "@odata.id": "SalesOrganizations('US')" } } },
- { "PaperSalesCount@odata.type": "Decimal", "PaperSalesCount": 1,
+ "Superordinate": { "@id": "SalesOrganizations('US')" } } },
+ { "PaperSalesCount@type": "Decimal", "PaperSalesCount": 1,
"SalesOrganization": { "ID": "US West", "Name": "US West",
- "Superordinate": { "@odata.id": "SalesOrganizations('US')" } } },
- { "PaperSalesCount@odata.type": "Decimal", "PaperSalesCount": 2,
+ "Superordinate": { "@id": "SalesOrganizations('US')" } } },
+ { "PaperSalesCount@type": "Decimal", "PaperSalesCount": 2,
"SalesOrganization": { "ID": "EMEA", "Name": "EMEA",
- "Superordinate": { "@odata.id": "SalesOrganizations('Sales')" } } },
- { "PaperSalesCount@odata.type": "Decimal", "PaperSalesCount": 2,
+ "Superordinate": { "@id": "SalesOrganizations('Sales')" } } },
+ { "PaperSalesCount@type": "Decimal", "PaperSalesCount": 2,
"SalesOrganization": { "ID": "EMEA Central", "Name": "EMEA Central",
- "Superordinate": { "@odata.id": "SalesOrganizations('EMEA')" } } },
- { "PaperSalesCount@odata.type": "Decimal", "PaperSalesCount": 4,
+ "Superordinate": { "@id": "SalesOrganizations('EMEA')" } } },
+ { "PaperSalesCount@type": "Decimal", "PaperSalesCount": 4,
"SalesOrganization": { "ID": "Sales", "Name": "Sales",
"Superordinate": null } }
]
@@ -1190,18 +1190,18 @@ GET /service/Sales?$apply=groupby(
results in
```json
{
- "@odata.context": "$metadata#Sales(SalesOrganization(ID),
+ "@context": "$metadata#Sales(SalesOrganization(ID),
TotalAmountIncl,TotalAmountExcl)",
"value": [
{ "SalesOrganization": { "ID": "US", "Name": "US" },
- "TotalAmountIncl@odata.type": "Decimal", "TotalAmountIncl": 19,
+ "TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 19,
"TotalAmountExcl": null },
{ "SalesOrganization": { "ID": "US East", "Name": "US East" },
- "TotalAmountIncl@odata.type": "Decimal", "TotalAmountIncl": 12,
- "TotalAmountExcl@odata.type": "Decimal", "TotalAmountExcl": 12 },
+ "TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 12,
+ "TotalAmountExcl@type": "Decimal", "TotalAmountExcl": 12 },
{ "SalesOrganization": { "ID": "US West", "Name": "US West" },
- "TotalAmountIncl@odata.type": "Decimal", "TotalAmountIncl": 7,
- "TotalAmountExcl@odata.type": "Decimal" ,"TotalAmountExcl": 7 }
+ "TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 7,
+ "TotalAmountExcl@type": "Decimal" ,"TotalAmountExcl": 7 }
]
}
```
@@ -1222,7 +1222,7 @@ GET /service/Products?$apply=traverse(
The result contains multiple instances of the same `Product` that differ in their `Sales` navigation property even though they agree in their `ID` key property. The node $x$ with $x/{\tt ID}={}$`"US"` has $σ(x)={}$`{"Sales": [{"SalesOrganization": {"ID": "US"}}]}`.
```json
{
- "@odata.context":
+ "@context":
"$metadata#Products(ID,Sales(SalesOrganization(ID)))",
"value": [
{ "ID": "P1", "Sales": [ { "SalesOrganization": { "ID": "Sales" } } ] },
@@ -1260,7 +1260,7 @@ GET /service/Products?$apply=
results in
```json
{
- "@odata.context": "$metadata#Products(Sales(SalesOrganization(ID)),
+ "@context": "$metadata#Products(Sales(SalesOrganization(ID)),
SoldProducts)",
"value": [
{ "Sales": [ { "SalesOrganization": { "ID": "Sales" } } ],
@@ -1314,17 +1314,17 @@ GET /service/Sales?$apply=groupby((rolluprecursive(
results in
```json
{
- "@odata.context": "$metadata#Sales(SalesOrganization(ID),TotalAmount)",
+ "@context": "$metadata#Sales(SalesOrganization(ID),TotalAmount)",
"value": [
{ "SalesOrganization": { "ID": "Sales", "ProductCategories": [ ] },
- "TotalAmount@odata.type": "Decimal", "TotalAmount": 24 },
+ "TotalAmount@type": "Decimal", "TotalAmount": 24 },
{ "SalesOrganization": { "ID": "US", "ProductCategories": [
- { "@odata.id": "ProductCategories('Food')" },
- { "@odata.id": "ProductCategories('Cereals')" } ] },
- "TotalAmount@odata.type": "Decimal", "TotalAmount": 19 },
+ { "@id": "ProductCategories('Food')" },
+ { "@id": "ProductCategories('Cereals')" } ] },
+ "TotalAmount@type": "Decimal", "TotalAmount": 19 },
{ "SalesOrganization": { "ID": "US West", "ProductCategories": [
- { "@odata.id": "ProductCategories('Organic cereals')" } ] },
- "TotalAmount@odata.type": "Decimal", "TotalAmount": 7 }
+ { "@id": "ProductCategories('Organic cereals')" } ] },
+ "TotalAmount@type": "Decimal", "TotalAmount": 7 }
]
}
```
@@ -1357,9 +1357,9 @@ GET /service/Sales?$apply=filter(Amount le 1)
means "filter first, then aggregate", and results in
```json
{
- "@odata.context": "$metadata#Sales(Total)",
+ "@context": "$metadata#Sales(Total)",
"value": [
- { "Total@odata.type": "Decimal", "Total": 2 }
+ { "Total@type": "Decimal", "Total": 2 }
]
}
```
@@ -1377,12 +1377,12 @@ GET /service/Sales?$apply=filter(Amount le 2)/groupby((Product/Name),
results in
```json
{
- "@odata.context": "$metadata#Sales(Product(Name),Total)",
+ "@context": "$metadata#Sales(Product(Name),Total)",
"value": [
{ "Product": { "Name": "Paper" },
- "Total@odata.type": "Decimal", "Total": 4 },
+ "Total@type": "Decimal", "Total": 4 },
{ "Product": { "Name": "Sugar" },
- "Total@odata.type": "Decimal", "Total": 4 }
+ "Total@type": "Decimal", "Total": 4 }
]
}
```
@@ -1411,13 +1411,13 @@ GET /service/Cities?$apply=groupby((Continent/Name,Country/Name),
results in
```json
{
- "@odata.context": "$metadata#Cities(Continent(Name),Country(Name),
+ "@context": "$metadata#Cities(Continent(Name),Country(Name),
TotalPopulation)",
"value": [
{ "Continent": { "Name": "Asia" }, "Country": { "Name": "China" },
- "TotalPopulation@odata.type": "Int32", "TotalPopulation": 1412000000 },
+ "TotalPopulation@type": "Int32", "TotalPopulation": 1412000000 },
{ "Continent": { "Name": "Asia" }, "Country": { "Name": "India" },
- "TotalPopulation@odata.type": "Int32", "TotalPopulation": 1408000000 },
+ "TotalPopulation@type": "Int32", "TotalPopulation": 1408000000 },
...
]
}
@@ -1507,15 +1507,15 @@ GET /service/Sales?$apply=groupby((Product/Category/ID),
results in
```json
{
- "@odata.context":"$metadata#Sales(Product(Category(ID)),Customers())",
+ "@context":"$metadata#Sales(Product(Category(ID)),Customers())",
"value": [
{ "Product": { "Category": { "ID": "PG1" } },
- "Customers@odata.context": "#Sales(Customer(ID))",
+ "Customers@context": "#Sales(Customer(ID))",
"Customers": [ { "Customer": { "ID": "C1" } },
{ "Customer": { "ID": "C2" } },
{ "Customer": { "ID": "C3" } } ] },
{ "Product": { "Category": { "ID": "PG2" } },
- "Customers@odata.context": "#Sales(Customer(ID))",
+ "Customers@context": "#Sales(Customer(ID))",
"Customers": [ { "Customer": { "ID": "C1" } },
{ "Customer": { "ID": "C2" } },
{ "Customer": { "ID": "C3" } } ] }
From a60efb96c44b504cbddb09ed99f6b674df3a8c7e Mon Sep 17 00:00:00 2001
From: D024504
Date: Fri, 26 May 2023 11:56:28 +0200
Subject: [PATCH 021/116] indentation
---
.../odata-data-aggregation-ext.html | 76 +++++++++----------
.../odata-data-aggregation-ext.md | 16 ++--
.../3.2 Basic Aggregation.md | 2 +-
.../6 Hierarchical Transformations.md | 2 +-
odata-data-aggregation-ext/7 Examples.md | 12 ++-
5 files changed, 51 insertions(+), 57 deletions(-)
diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
index 654f22160..27e2d55a1 100644
--- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
+++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
@@ -2844,7 +2844,7 @@ 3.2.1.2
{
"@context": "$metadata#Sales(Customer(Country),
- Product(Category(Name)),Total)",
+ Product(Category(Name)),Total)",
"value": [
{ "Customer": { "Country": "USA", "Name": "Joe" },
"Product": { "Category": { "Name": "Non-Food" }, "Name": "Paper" },
@@ -5007,7 +5007,7 @@ 5.5
{
"@context": "$metadata#Sales(SalesOrganization(),
- TotalAmountIncl,TotalAmountExcl)",
+ TotalAmountIncl,TotalAmountExcl)",
"value": [
{ "SalesOrganization": { "ID": "US West", "Name": "US West" },
"TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 7,
@@ -5197,7 +5197,7 @@ 7
{
"@context": "$metadata#Products(SalesModel.FoodProduct/Rating,
- SalesModel.NonFoodProduct/RatingClass)",
+ SalesModel.NonFoodProduct/RatingClass)",
"value": [
{ "@type": "#SalesModel.FoodProduct", "Rating": 5 },
{ "@type": "#SalesModel.FoodProduct", "Rating": null },
@@ -5544,23 +5544,22 @@ 7
results in
{
-"@context": "$metadata#Customers(
- Addresses(AugmentedSalesOrganization())",
-"value": [
- { "ID": "C1", "Name": "Joe", "Country": "US",
- "Addresses": [
- { "Locality": "Seattle",
- "AugmentedSalesOrganization":
- { "@context": "#SalesOrganizations/$entity",
- "ID": "US West", "SalesRegion": "US" } },
- { "Locality": "DC",
- "AugmentedSalesOrganization":
- { "@context": "#SalesOrganizations/$entity",
- "ID": "US", "SalesRegion": "Corporate Sales" } },
- ]
- }, ...
- ]
- }
+"@context": "$metadata#Customers(Addresses(AugmentedSalesOrganization())",
+ "value": [
+ { "ID": "C1", "Name": "Joe", "Country": "US",
+ "Addresses": [
+ { "Locality": "Seattle",
+ "AugmentedSalesOrganization":
+ { "@context": "#SalesOrganizations/$entity",
+ "ID": "US West", "SalesRegion": "US" } },
+ { "Locality": "DC",
+ "AugmentedSalesOrganization":
+ { "@context": "#SalesOrganizations/$entity",
+ "ID": "US", "SalesRegion": "Corporate Sales" } },
+ ]
+ }, ...
+ ]
+ }
addnested
transformations can be nested.
@@ -6202,7 +6201,7 @@ 7.4
{
"@context": "$metadata#Sales(SalesOrganization(ID),
- TotalAmountIncl,TotalAmountExcl)",
+ TotalAmountIncl,TotalAmountExcl)",
"value": [
{ "SalesOrganization": { "ID": "US", "Name": "US" },
"TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 19,
@@ -6272,23 +6271,22 @@ 7.4
results in
{
-"@context": "$metadata#Products(Sales(SalesOrganization(ID)),
- SoldProducts)",
-"value": [
- { "Sales": [ { "SalesOrganization": { "ID": "Sales" } } ],
- "SoldProducts": "P1,P2,P3" },
- { "Sales": [ { "SalesOrganization": { "ID": "EMEA" } } ],
- "SoldProducts": "P1,P3" },
- { "Sales": [ { "SalesOrganization": { "ID": "EMEA Central" } } ],
- "SoldProducts": "P1,P3" },
- { "Sales": [ { "SalesOrganization": { "ID": "US" } } ],
- "SoldProducts": "P1,P2,P3" },
- { "Sales": [ { "SalesOrganization": { "ID": "US East" } } ],
- "SoldProducts": "P2,P3" },
- { "Sales": [ { "SalesOrganization": { "ID": "US West" } } ],
- "SoldProducts": "P1,P2,P3" }
- ]
- }
+"@context": "$metadata#Products(Sales(SalesOrganization(ID)),SoldProducts)",
+ "value": [
+ { "Sales": [ { "SalesOrganization": { "ID": "Sales" } } ],
+ "SoldProducts": "P1,P2,P3" },
+ { "Sales": [ { "SalesOrganization": { "ID": "EMEA" } } ],
+ "SoldProducts": "P1,P3" },
+ { "Sales": [ { "SalesOrganization": { "ID": "EMEA Central" } } ],
+ "SoldProducts": "P1,P3" },
+ { "Sales": [ { "SalesOrganization": { "ID": "US" } } ],
+ "SoldProducts": "P1,P2,P3" },
+ { "Sales": [ { "SalesOrganization": { "ID": "US East" } } ],
+ "SoldProducts": "P2,P3" },
+ { "Sales": [ { "SalesOrganization": { "ID": "US West" } } ],
+ "SoldProducts": "P1,P2,P3" }
+ ]
+ }
⚠ Example 109: Assume an extension of the data model where a
@@ -6439,7 +6437,7 @@
7.4
{
"@context": "$metadata#Cities(Continent(Name),Country(Name),
- TotalPopulation)",
+ TotalPopulation)",
"value": [
{ "Continent": { "Name": "Asia" }, "Country": { "Name": "China" },
"TotalPopulation@type": "Int32", "TotalPopulation": 1412000000 },
diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
index bed978ba7..e8f828e75 100644
--- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
+++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md
@@ -1547,7 +1547,7 @@ results in seven entities for the finest grouping level
```json
{
"@context": "$metadata#Sales(Customer(Country),
- Product(Category(Name)),Total)",
+ Product(Category(Name)),Total)",
"value": [
{ "Customer": { "Country": "USA", "Name": "Joe" },
"Product": { "Category": { "Name": "Non-Food" }, "Name": "Paper" },
@@ -2952,7 +2952,7 @@ results in
```json
{
"@context": "$metadata#Sales(SalesOrganization(),
- TotalAmountIncl,TotalAmountExcl)",
+ TotalAmountIncl,TotalAmountExcl)",
"value": [
{ "SalesOrganization": { "ID": "US West", "Name": "US West" },
"TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 7,
@@ -3139,7 +3139,7 @@ results in
```json
{
"@context": "$metadata#Products(SalesModel.FoodProduct/Rating,
- SalesModel.NonFoodProduct/RatingClass)",
+ SalesModel.NonFoodProduct/RatingClass)",
"value": [
{ "@type": "#SalesModel.FoodProduct", "Rating": 5 },
{ "@type": "#SalesModel.FoodProduct", "Rating": null },
@@ -3502,8 +3502,7 @@ GET /service/Customers?$apply=
results in
```json
{
- "@context": "$metadata#Customers(
- Addresses(AugmentedSalesOrganization())",
+ "@context": "$metadata#Customers(Addresses(AugmentedSalesOrganization())",
"value": [
{ "ID": "C1", "Name": "Joe", "Country": "US",
"Addresses": [
@@ -4196,7 +4195,7 @@ results in
```json
{
"@context": "$metadata#Sales(SalesOrganization(ID),
- TotalAmountIncl,TotalAmountExcl)",
+ TotalAmountIncl,TotalAmountExcl)",
"value": [
{ "SalesOrganization": { "ID": "US", "Name": "US" },
"TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 19,
@@ -4265,8 +4264,7 @@ GET /service/Products?$apply=
results in
```json
{
- "@context": "$metadata#Products(Sales(SalesOrganization(ID)),
- SoldProducts)",
+ "@context": "$metadata#Products(Sales(SalesOrganization(ID)),SoldProducts)",
"value": [
{ "Sales": [ { "SalesOrganization": { "ID": "Sales" } } ],
"SoldProducts": "P1,P2,P3" },
@@ -4417,7 +4415,7 @@ results in
```json
{
"@context": "$metadata#Cities(Continent(Name),Country(Name),
- TotalPopulation)",
+ TotalPopulation)",
"value": [
{ "Continent": { "Name": "Asia" }, "Country": { "Name": "China" },
"TotalPopulation@type": "Int32", "TotalPopulation": 1412000000 },
diff --git a/odata-data-aggregation-ext/3.2 Basic Aggregation.md b/odata-data-aggregation-ext/3.2 Basic Aggregation.md
index 4180c15c8..71f5bddd5 100644
--- a/odata-data-aggregation-ext/3.2 Basic Aggregation.md
+++ b/odata-data-aggregation-ext/3.2 Basic Aggregation.md
@@ -464,7 +464,7 @@ results in seven entities for the finest grouping level
```json
{
"@context": "$metadata#Sales(Customer(Country),
- Product(Category(Name)),Total)",
+ Product(Category(Name)),Total)",
"value": [
{ "Customer": { "Country": "USA", "Name": "Joe" },
"Product": { "Category": { "Name": "Non-Food" }, "Name": "Paper" },
diff --git a/odata-data-aggregation-ext/6 Hierarchical Transformations.md b/odata-data-aggregation-ext/6 Hierarchical Transformations.md
index 7cd072b9b..08d6c894a 100644
--- a/odata-data-aggregation-ext/6 Hierarchical Transformations.md
+++ b/odata-data-aggregation-ext/6 Hierarchical Transformations.md
@@ -416,7 +416,7 @@ results in
```json
{
"@context": "$metadata#Sales(SalesOrganization(),
- TotalAmountIncl,TotalAmountExcl)",
+ TotalAmountIncl,TotalAmountExcl)",
"value": [
{ "SalesOrganization": { "ID": "US West", "Name": "US West" },
"TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 7,
diff --git a/odata-data-aggregation-ext/7 Examples.md b/odata-data-aggregation-ext/7 Examples.md
index 25e4db50e..14cfc7dac 100644
--- a/odata-data-aggregation-ext/7 Examples.md
+++ b/odata-data-aggregation-ext/7 Examples.md
@@ -134,7 +134,7 @@ results in
```json
{
"@context": "$metadata#Products(SalesModel.FoodProduct/Rating,
- SalesModel.NonFoodProduct/RatingClass)",
+ SalesModel.NonFoodProduct/RatingClass)",
"value": [
{ "@type": "#SalesModel.FoodProduct", "Rating": 5 },
{ "@type": "#SalesModel.FoodProduct", "Rating": null },
@@ -497,8 +497,7 @@ GET /service/Customers?$apply=
results in
```json
{
- "@context": "$metadata#Customers(
- Addresses(AugmentedSalesOrganization())",
+ "@context": "$metadata#Customers(Addresses(AugmentedSalesOrganization())",
"value": [
{ "ID": "C1", "Name": "Joe", "Country": "US",
"Addresses": [
@@ -1191,7 +1190,7 @@ results in
```json
{
"@context": "$metadata#Sales(SalesOrganization(ID),
- TotalAmountIncl,TotalAmountExcl)",
+ TotalAmountIncl,TotalAmountExcl)",
"value": [
{ "SalesOrganization": { "ID": "US", "Name": "US" },
"TotalAmountIncl@type": "Decimal", "TotalAmountIncl": 19,
@@ -1260,8 +1259,7 @@ GET /service/Products?$apply=
results in
```json
{
- "@context": "$metadata#Products(Sales(SalesOrganization(ID)),
- SoldProducts)",
+ "@context": "$metadata#Products(Sales(SalesOrganization(ID)),SoldProducts)",
"value": [
{ "Sales": [ { "SalesOrganization": { "ID": "Sales" } } ],
"SoldProducts": "P1,P2,P3" },
@@ -1412,7 +1410,7 @@ results in
```json
{
"@context": "$metadata#Cities(Continent(Name),Country(Name),
- TotalPopulation)",
+ TotalPopulation)",
"value": [
{ "Continent": { "Name": "Asia" }, "Country": { "Name": "China" },
"TotalPopulation@type": "Int32", "TotalPopulation": 1412000000 },
From 6de8c2ee99237c53df5f3b53f9bcf94052bf19f6 Mon Sep 17 00:00:00 2001
From: D024504
Date: Fri, 26 May 2023 14:52:23 +0200
Subject: [PATCH 022/116] typos
---
.../odata-data-aggregation-ext.html | 6 +++---
.../odata-data-aggregation-ext.md | 2 +-
.../3.1 Fundamentals of Input and Output Sets.md | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
index 27e2d55a1..1a3cdc9ec 100644
--- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
+++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
@@ -1981,9 +1981,9 @@ 2.2
class="math inline">\(u_1\) is processed before \(u_2\) whenever \(u_1\) precedes \(u_2\). Likewise, in an order-preserving
-sequence \(u_1,…,u_n\) we have \(i<j\) whenever \(u_2\). Likewise, in an order-preserving
+sequence \(u_1,…,u_n\) we have
+\(i<j\) whenever \(u_i\) precedes \(u_j\).
The transformation
Date: Fri, 26 May 2023 17:16:12 +0200
Subject: [PATCH 023/116] TC 2023-05-31 - additions Ralf (#12)
---
.../odata-data-aggregation-ext.html | 2982 ++++++++---------
.../odata-data-aggregation-ext.md | 340 +-
odata-data-aggregation-ext/1 Introduction.md | 3 +-
...1 Fundamentals of Input and Output Sets.md | 12 +-
.../3.2 Basic Aggregation.md | 45 +-
...ions Preserving the Input Set Structure.md | 2 +-
...ations Changing the Input Set Structure.md | 2 +-
...5 Expressions Evaluable on a Collection.md | 4 +-
.../6 Hierarchical Transformations.md | 4 +-
odata-data-aggregation-ext/7 Examples.md | 14 +-
odata-data-aggregation-ext/8 Conformance.md | 28 +-
11 files changed, 1731 insertions(+), 1705 deletions(-)
diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
index 27e2d55a1..36b3804c2 100644
--- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
+++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html
@@ -483,6 +483,11 @@ 1.1
Expression – an expression resulting
in a value of an aggregatable
primitive type
+
- Aggregate Expression –
+argument of the
aggregate
transformation or function defined in section 3.2.1.1
- Aggregatable Primitive
Type – a primitive type other than
Edm.Stream
or
subtypes of Edm.Geography
or Edm.Geometry
@@ -518,7 +523,7 @@ 1.1
- \(S,T\) – transformation
sequences
- \(α\) – aggregate expression,
-defined below
+defined in section 3.2.1.1
- \(\Gamma(A,p)\) – the collection
that results from evaluating a data
aggregation path \(p\) relative to
@@ -1841,13 +1846,13 @@
2.2
determined by the entity model element identified within the metadata
document by the context URL of that resource OData-Protocol, section 10. Individual
-instances in an input or output set can have a subtype of the input
-type. (See example 69.) The transformation
-sequence given as the $apply
system query option is applied
-to the resource addressed by the resource path. The transformations
-defined below can have nested transformation sequences as parameters,
-these are then applied to resources that can differ from the current
-input set.
+structured instances in an input or output set can have a subtype of the
+input type. (See example 70.) The
+transformation sequence given as the $apply
system query
+option is applied to the resource addressed by the resource path. The
+transformations defined below can have nested transformation sequences
+as parameters, these are then applied to resources that can differ from
+the current input set.
The structure of an instance that occurs in an input or
output set is defined by the names of the structural and navigation
properties that the instance contains. Instances of an input type can
@@ -1913,21 +1918,21 @@
2.2
properties, the {select-list}
MUST consist of just the
instance annotation AnyStructure
defined in the
Core
vocabulary OData-VocCore.
-(See example 70.)
+(See example 71.)
3.1.2
Sameness and Precedence
Input sets and output sets are not sets of instances in the
mathematical sense but collections, because the same instance can occur
multiple times in them. In other words: A collection contains values
-(which can be instances or primitive values), possibly with repetitions.
-The occurrences in the collection form a set in the mathematical sense.
-The cardinality of a collection is the total number of
-occurrences in it. When this text describes a transformation
-algorithmically and stipulates that certain steps are carried out
-for each instance in a collection, this means that the steps
-are carried out multiple times for the same instance if it occurs
-multiple times in the collection.
+(which can be structured instances or primitive values), possibly with
+repetitions. The occurrences in the collection form a set in the
+mathematical sense. The cardinality of a collection is the
+total number of occurrences in it. When this text describes a
+transformation algorithmically and stipulates that certain steps are
+carried out for each instance in a collection, this means that
+the steps are carried out multiple times for the same instance if it
+occurs multiple times in the collection.
A collection addressed by the resource path is returned by the
service either as an ordered collection OData-Protocol, section 11.4.10 or as an
@@ -2008,28 +2013,27 @@
2.2
collection may still contain two occurrences whose relative order does
not matter.
The output set of a basic aggregation
-transformation can contain instances of an entity type without
-entity-id. After a concat
transformation,
-different occurrences of the same entity can differ in individual
-non-declared properties. To account for such cases, the definition of
-sameness given in OData-URL, section 5.1.1.1.1
-is refined here. Instances are the same if
+transformation can contain instances of an entity type without entity
+id. After a concat
+transformation, different occurrences of the same entity can differ in
+individual non-declared properties. To account for such cases, the
+definition of sameness given in OData-URL, section
+5.1.1.1.1 is refined here. Instances are the same if
- both are instances of complex types and both are null or both have
the same structure and same values with null considered different from
absent or
-- both are instances of entity types without entity-id (transient
+
- both are instances of entity types without entity id (transient
entities, see OData-Protocol, section 4.3)
and both are null or both have the same structure and same values with
null considered different from absent (informally speaking, they are
compared like complex instances) or
-- (1) both are instances of the same entity type with the same
-entity-id (non-transient entities, see OData-Protocol, section 4.1) and (2) the
-structural and navigation properties contained in both have the same
-values (for non-primitive properties the sameness of values is decided
-by a recursive invocation of this definition).
+
- (1) both are instances of the same entity type with the same entity
+id (non-transient entities, see OData-Protocol,
+section 4.1) and (2) the structural and navigation properties
+contained in both have the same values (for non-primitive properties the
+sameness of values is decided by a recursive invocation of this
+definition).
- If this is fulfilled, the instances are called complementary
representations of the same non-transient entity. If this case is
@@ -2045,7 +2049,7 @@
2.2
- If the first condition is fulfilled but not the second, the
instances are not the same and are called contradictory
representations of the same non-transient entity. (Example 98 describes a use case for this.)
+href="#contradict">Example 99 describes a use case for this.)
Collections are the same if there is a one-to-one
@@ -2072,10 +2076,11 @@
2.2
For a data aggregation path to be a common expression according to OData-URL, section 5.1.1, its segments must be
single-valued with the possible exception of the last segment, and it
-can then be evaluated relative to an instance. For the transformations
-defined in this document, a data aggregation path can also be evaluated
-relative to a collection \(A\), even if
-it has arbitrary collection-valued segments itself.
+can then be evaluated relative to a structured instance. For the
+transformations defined in this document, a data aggregation path can
+also be evaluated relative to a collection \(A\), even if it has arbitrary
+collection-valued segments itself.
To this end, the following notation is used in the subsequent
sections: If \(A\) is a collection and
\(p\) a data aggregation path,
@@ -2154,23 +2159,25 @@
2.2
id="3211-aggregation-algorithm">3.2.1.1
Aggregation Algorithm
The aggregate
transformation takes a comma-separated
-list of one or more aggregate expressions as parameters and
-returns an output set with a single instance of the input type without entity-id
-containing one property per aggregate expression, representing the
-aggregated value of the input set.
-An aggregate expression MUST have one of the types listed below. To
-compute the value of the property for a given aggregate expression, the
-aggregate
transformation first determines a collection
-\(A\) of instances or primitive values,
-based on the input set of the aggregate
transformation, and
-a path \(p\) that occurs in the
-aggregate expression. Let \(p_1\)
-denote a data aggregation path with
-single- or collection-valued segments and \(p_2\) a type-cast segment. Depending on the
-type of aggregate expression, \(p=p_1\)
-or \(p=p_2\) or aggregate
+expressions
as parameters and returns an output set with a
+single instance of the input
+type without entity id containing one property per aggregate
+expression, representing the aggregated value of the input set.
+
An aggregate expression MUST have one of the types listed below or be
+constructed with the from
+keyword. To compute the value of the property for a given aggregate
+expression, the aggregate
transformation first determines a
+collection \(A\) of structured
+instances or primitive values, based on the input set of the
+aggregate
transformation, and a path \(p\) that occurs in the aggregate
+expression. Let \(p_1\) denote a data aggregation path with single- or
+collection-valued segments and \(p_2\)
+a type-cast segment. Depending on its type, the aggregate expression
+contains a path \(p=p_1\) or \(p=p_2\) or \(p=p_1/p_2\). Each type of aggregate
expression defines a function \(f(A)\)
which the aggregate transformation evaluates to obtain the property
@@ -2179,13 +2186,11 @@
2.2
4. In types 1 and 2, the aggregate expression MUST end with the keyword
with
and an aggregation method \(g\). The aggregation method also determines
-the type of the dynamic property. In types 1, 2 and 3 the aggregate
+the type of the dynamic property. In types 1, 2, and 3 the aggregate
expression MUST, and in type 4 it MAY, be followed by the keyword as
and an alias, which is then the name of
-the dynamic property. More aggregate expressions can be constructed with
-the from
keyword, see later
-section.
+the dynamic property.
Types of aggregate expressions:
- A path \(p=p_1\) or 2.2
href="#CustomAggregates">custom aggregate \(c\) defined on the collection addressed by
\(p\).
-Let \(f(A)=c(A)\), if computation of
-the custom aggregate fails, the service MUST reject the request. In the
-absence of an alias, the name of the property MUST be the name of the
-custom aggregate, this is a dynamic property unless there is a declared
-property with that name, which is allowed by the
+Let \(f(A)=c(A)\), and if computation
+of the custom aggregate fails, the service MUST reject the request. In
+the absence of an alias, the name of the property MUST be the name of
+the custom aggregate, this is a dynamic property unless there is a
+declared property with that name, which is allowed by the
CustomAggregate
annotation. The custom aggregate also
determines the type of the dynamic property.
@@ -2257,7 +2262,7 @@ 2.2
service MUST merge them into one occurrence in \(E\) if they are complementary and MUST
reject the request if they are contradictory. (See example 119.) If example 120.) If multiple occurrences of the same transient
entity are reached, the service MUST keep only one occurrence in
\(E\).
@@ -2266,8 +2271,8 @@ 2.2
Then, if \(r\) is empty, let \(A=E\), otherwise let \(A=\Gamma(E,r)\), this consists of instances
-or primitive values, possibly with repetitions.
+class="math inline">\(A=\Gamma(E,r)\), this consists of
+structured instances or primitive values, possibly with repetitions.
3.2.1.2
Keyword as
Aggregate expressions can define an 3.2.1.2
The standard aggregation method max
can be applied to
values with a totally ordered domain to return the largest of the
values, or null if there are no values to be aggregated.
-The result property will have the same type as the input property
+The result property will have the same type as the input
+property.
Example 11:
GET /service/Sales?$apply=aggregate(Amount with max as MaxAmount)
@@ -2382,9 +2388,8 @@ 3.2.1.2
id="32134-standard-aggregation-method-average">3.2.1.3.4
Standard Aggregation Method average
The standard aggregation method average
can be applied
-to numeric values to return the sum of the non-null values divided by
-the count of the values, or null if there are no values to be
-aggregated.
+to numeric values to return the sum of the values divided by the count
+of the values, or null if there are no values to be aggregated.
The provider MUST choose a single type for the property across all
instances of that type in the result that is capable of representing the
aggregated values; either Edm.Double
or
@@ -2486,7 +2491,7 @@
3.2.1.2
href="Transformationgroupby">groupby
and aggregate
transformations with the pattern \({\tt
-groupby}(…,{\tt aggregate}(…{\tt\ as\ }A_1))/{\tt aggregate}(A_1{\tt\
+groupby}(…,{\tt aggregate}(…{\tt\ as\ }D_1))/{\tt aggregate}(D_1{\tt\
with\ }…)\).
In the following \(p_1,…,p_n\) are
data aggregation paths that are
@@ -2500,7 +2505,7 @@
3.2.1.2
property \(D\) in the single instance
in the output set of the following transformation sequence: \[{\tt groupby}((p_1,…,p_n),{\tt aggregate}(α{\tt\
-as\ }A_1))/{\tt aggregate}(A_1{\tt\ with\ }g{\tt\ as\ }D).\]
+as\ }D_1))/{\tt aggregate}(D_1{\tt\ with\ }g{\tt\ as\ }D).\]
- If \(α=p/c{\tt\ from\ }…\) is an
aggregate expression that starts with a custom aggregate \(c\), optionally prefixed with a path 3.2.1.2
value of property \(c\) in the single
instance in the output set of the following transformation sequence:
\[{\tt groupby}((p_1,…,p_n),{\tt
-aggregate}(α{\tt\ as\ }A_1))/{\tt aggregate}(p/c).\]
+aggregate}(α{\tt\ as\ }D_1))/{\tt aggregate}(p/c).\]
Aggregate expressions constructed by these rules MUST be followed in
the aggregate
transformation by the keyword as
@@ -2550,6 +2555,19 @@
3.2.1.2
GET /service/Sales?$apply=groupby((Time),aggregate(Forecast))
/aggregate(Forecast with average as DailyAverage)
+
+⚠ Example 18: the maximal daily average for sales of a product
+GET /service/Sales?$apply=aggregate(Amount with average from Time,Product/Name
+ with max as MaxDailyAverage)
+results in
+{
+"@context": "$metadata#Sales(MaxDailyAverage)",
+ "value": [
+ { "MaxDailyAverage@type": "Decimal", "MaxDailyAverage": 8 }
+ ]
+ }
+
3.2.2
Transformation concat
@@ -2564,19 +2582,19 @@ 3.2.1.2
same alias, clients SHOULD ensure they have the same type and meaning in
each intermediate output set.
-⚠ Example 18:
+⚠ Example 19:
GET /service/Sales?$apply=concat(topcount(2,Amount),
aggregate(Amount))
results in
-{
-"@context": "$metadata#Sales(Amount)",
- "value": [
- { "ID": 4, "Amount": 8 },
- { "ID": 3, "Amount": 4 },
- { "Amount": 24 }
- ]
- }
+{
+"@context": "$metadata#Sales(Amount)",
+ "value": [
+ { "ID": 4, "Amount": 8 },
+ { "ID": 3, "Amount": 4 },
+ { "Amount": 24 }
+ ]
+ }
Note that two Sales entities with the second highest amount 4 exist
in the input set; the entity with ID
3 is included in the
result, because the service chose to use the ID
property
@@ -2593,7 +2611,7 @@
3.2.1.2
parameter is not specified, it defaults to a single transformation whose
output set consists of a single instance of the input type without properties and
-without entity-id.
+without entity id.
3.2.3.1
Simple Grouping
@@ -2605,7 +2623,7 @@ 3.2.1.2
redundant property paths MAY be considered valid, but MUST NOT alter the
meaning of the request. Navigation properties and stream properties
specified in grouping properties are expanded by default (see example 67).
+href="#groupbynav">example 68).
The algorithmic description of this transformation makes use of the
following definitions: Let \(u[q]\)
denote the value of a structural or navigation property 3.2.1.2
- Let \(v\) be an instance of the
type of \(u\) without properties and
-without entity-id.
+without entity id.
- For each structural or navigation property \(q\) of \(u\):
@@ -2721,51 +2739,51 @@
3.2.1.2
- Return \(u\).
-Example 19:
+Example 20:
GET /service/Sales?$apply=groupby((Customer/Country,Product/Name),
aggregate(Amount with sum as Total))
results in
-