Skip to main content

Measure and hierarchy publication

Publishing a measure or hierarchy is the process through which the Copper context is made aware of its existence. At the end of the Copper calculations, all published measures and hierarchies are added to the cube description.

After a successful publication, a measure or hierarchy becomes available in the following calculations. It can be retrieved by name.

The name of a measure is either user-defined, or automatically generated by Copper using its main characteristics (type of measure, arithmetic operator, name of underlying measures, levels of aggregation, ...). The name of a hierarchy is user-defined.

Measures that are published by the user must be named. Copper can only rename measures that are not visible.

Copper.sum("likes").withName("likes.SUM").publish(context); // measure "likes.SUM" becomes available
Copper.measure("likes.SUM")
.per(Copper.level("sender_id"))
.doNotAggregateAbove()
.withName("likes.SUM per sender") // "likes.SUM per sender" overwrites
// "likes.SUM.per(sender).doNotAggregateAbove()"
.publish(context); // measure "likes.SUM per sender" becomes available
Copper.measure("likes.SUM per sender")
.multiply(Copper.constant(2))
.withName("likes.SUM per sender times 2")
.publish(context); // measure "λ(likes.SUM per sender)" becomes available
Copper.newHierarchy("bucket", "bucket")
.fromValues(Copper.level("month").map((Integer m) -> "Q" + ((m - 1) / 3 + 1)))
.withLevelName("Quarter")
.publish(context); // hierarchy and level "Quarter" become available
Copper.measure("likes.SUM")
.shift(Copper.level("bucket", "bucket", "Quarter").at(s -> "Q4"))
.withName("likes.SUM at Quarter level")
.publish(context); // measure "likes.SUM.at(Quarter)" becomes available

Regarding measures

Publishing a measure also publishes all intermediary measures used in its definition. Unless specified with the use of visible(), these intermediary measures are hidden in the UI, but are still available in queries.

Copper.sum("likes") // creates "likes.SUM"
.per(Copper.level("sender_id"))
.avg() // creates "likes.SUM.per(sender_id).avg()"
.withName("myMeasure") // "myMeasure" overwrites "likes.SUM.per(sender_id).avg()"
.publish(context); // publishes "pnl.SUM" and "myMeasure"

Defining the same measure several times across the Copper calculations is not an issue, since Copper can detect when the same measure has already been published, and won't perform the same work twice. However, trying to publish a measure which has the same name as an already published measure will throw an exception.

When Copper generates intermediary measures, it will attribute a unique name to each of them.