C3 AI Documentation Home

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 timestamp and continue until another replaces them. They also have a parametric from and to field to represent the relationship.
  • TimedIntervalRelation is a TimedRelation with both a start and end datetime.
  • 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 start and end.

TimedValue example

The following is an example of TimedValue with TimedCharacteristicHistory and TimedValueHistory mixed in.

Type
// 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.

  • 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.

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 time

  • MeterAsset.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 range

  • MeterAsset.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).

Caveats

The following caveats must be observed with this feature:

  • Any non-array timed value field (for example, ServicePoint.servicePointStatus in the above example) is null when using timed fetch.
  • Stored calc fields 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.

See also

Was this page helpful?