Use Timed Types
In addition to Timeseries, certain data types may be used to represent data that changes over time, such as the relationship between customers and electrical meters that changes based on who had the active customer account during a specific time.
Timed Types
When performing a timed fetch, any arrays of "timed" values are filtered to only return values corresponding to the requested time or time range. The following types (and those that mix them in) are affected in timed fetches:
- TimedRelation represents relationships that have a start date signified by the
timestampand continue until another replaces them. They also have a parametricfromandtofield to represent the relationship. - TimedIntervalRelation is a TimedRelation with both a
startandenddatetime. - TimedValue represents a value that is tied to a
timestamp, such as the number of people living in a house. - TimedIntervalValue is a TimedValue with a
startandend.
TimedValue example
The following is an example of TimedValue with TimedCharacteristicHistory and TimedValueHistory mixed in.
// TimedCharacteristicHistory mixes TimedValueHistory mixes TimedValue
entity type ServicePointCharacteristicSet mixes TimedCharacteristicHistory<ServicePoint>, String ...
// TimedValueHistory mixes TimedValue
entity type ServicePointStatusSet mixes TimedValueHistory<ServicePoint>, String...
extendable entity type ServicePoint extends LocationMeasurementDevice mixes MetricEvaluatable type key 'SP' {
...
characteristics : [ServicePointCharacteristicSet](parent)
// Status set fields
@db(order = "descending(timestamp)")
servicePointStatusSet : [ServicePointStatusSet](parent)
// latest status (calculated)
@db(timedValuesField = "servicePointStatusSet")
servicePointStatus : ServicePointStatus
}Use the following code snippet examples to obtain the desired outcome defined below.
ServicePoint.fetch({asOf: '2014-01-01T00:00:00Z'})returns all service points with the values in the characteristics and servicePointStatusSet fields containing only the values (single value only for servicePointStatus since there can only be one valid value at any point in time) as they were at that time.ServicePoint.fetch({timeRange: TimeRange.make({start: '2014-01-01T00:00:00Z', end: '2015-01-01T00:00:00Z'})})returns all service points with the values in the characteristics and servicePointStatusSet fields containing only the values as they were at any point in time in the specified range.
In both cases, the field servicePointStatus is null. That field populates with the latest value chronologically only during a non-timed fetch.
ServicePoint.tsEval({projection : "servicePointStatusSet.value", start: '2014-01-01T00:00:00Z', end: '2015-01-01T00:00:00Z', interval: "MONTH"})returns just the values for the time range specified.
See also ServicePoint.
TimedRelation example
The following is an example of TimedIntervalRelation mixed in with a ServicePointMeterAsset Type.
entity type ServicePointMeterAsset mixes TimedIntervalRelation<ServicePoint, MeterAsset> ...
extendable entity type MeterAsset extends GridAsset type key 'METER' {
...
@db(order = "descending(start), descending(end)")
servicePointMappings : [ServicePointMeterAsset](to)
}Use the following code snippet examples to obtain the desired outcome defined below.
MeterAsset.fetch({asOf: '2014-01-01T00:00:00Z'})returns all meter assets with the values in the servicePointMappings field containing only the mappings to service points that were valid at that timeMeterAsset.fetch({timeRange: TimeRange.make({start: '2014-01-01T00:00:00Z', end: '2015-01-01T00:00:00Z'})})return all meter assets with the values in the servicePointMappings field containing only the mappings to service points that were valid at any point in the specified time rangeMeterAsset.tsEval({projection : "servicePointMappings.to.id", start: '2014-01-01T00:00:00Z', end: '2015-01-01T00:00:00Z', interval: "MONTH"})only returns ServicePoint IDs where the ServicePointMeterAsset is valid during that time range.
Nesting example
Using the above definitions for ServicePoint and MeterAsset: MeterAsset.fetch({include: "servicePointMappings.from.servicePointStatusSet", asOf: '2014-01-01T00:00:00Z'}) returns all MeterAssets with only the servicePointMappings that were valid at that time.
For each servicePointMapping returned, the service point and its status at that point in time are returned (for example, the requested time range is applied across all references in the include spec).
When to use timed Types instead of Timeseries
Timed data types should be used when the data is sparse or very slowly changing.
Use Timeseries for data that primarily represents values changing over time. This include measurements that come in periodically, such as every day or every month, or values that come in frequently but not necessarily periodically, such as temperature readings from a pump. These sort of data should have a natural normalization strategy (for example, divide the monthly value evenly into daily fractions, or use the last reading until the next comes in).
Use timed data types for data that is infrequently changing or would not normally be thought of as a series, such as the square area of a house (may change as the house is remodeled, but generally is set), the owner of a pump, or the status of a meter (for a summer home, it may only be "active" from May until September).
You can access Timeseries data directly in SimpleMetric expressions (see also ExpressionEngineFunction) through its normalized value, such as myField.normalized.quantity. For timed data types though, you must first convert the values into a timeseries. You can achieve this conversion in SimpleMetrics by using the tsDecl field, which explicitly defines the start, end, value, and treatment (see TSDecl) when converting the stored data into a timeseries.
Caveats
The following caveats must be observed with this feature:
- Any non-array timed value field (for example,
ServicePoint.servicePointStatusin the above example) is null when using timed fetch. - Stored
calcfields based on timed value fields are simply returned with their stored value, which is not expected to be relevant/valid in the timed fetch requested time range.