Skip to content

Filters

Filtering activities is most likely the core concept of Tracs. Almost all commands (apart from a few exceptions) work based on filters, like for instance listing activities. Commands apply filters on all known activities and work on the subset of activities which match those filters. The general form of a filter is this

[FIELD][OPERATOR][EXPRESSION]

There are exceptions to this form for convenience, which are explained later in this section. Multiple filters can be combined and are treated with a logical AND.

Fields

As you have learned in the section about activities, each activity has a number of attributes. Those can be used as fields in filters. Note that there are more fields than attributes! An obvious example for an attribute is time which is the time when an activity took place. However, there is a field year, which represents the year of the activity. There is no attribute year (at least no physical one, which is stored in the db), however it still can be used as a filter.

Filters (and attributes) have types like string, int or dates, which obviously restrict the expressions which can be used with them. A duration cannot be a string like Berlin. If you try things like that, a rule syntax error will be shown.

Valid field names can only consist of lower case letters, underscores and numbers. The first character must be a letter.

Operators

An operator compares a field against an expression. Currently, the following operators are supported:

Operator Explanation
== Equal, matches if field has an equal value compared to the expression
= Short form of ==, for convenience
: "Smart" equal, see below for further explaination
!= Not equal, matches if field and expression have non-equal values
=~ Same as equal, but expression represents a regular expression
!~ Same as not equal, but expression represents a regular expression
>= Greater than or equal, only works with numeric fields
> Greater than, only works with numeric fields
<= Less than or equal, only works with numeric fields
< Less than, only works with numeric fields

Important: note that depending on the shell you are using the filter needs to be escaped, as the shell may for example interpret the character > as a pipe.

Colon Operator, or Smart Equal Operator

Filters are based on an underlying rules of a rule engine, which is responsible for evaluation if an activity matches a filter or not (see https://zerosteiner.github.io/rule-engine/syntax.html) for more details. A filter is parsed and handed to the rule engine more or less unchanged - with one exception: the colon operator. The colon operator plays the role of a "smart equal" operator and allows shorter and more convenient expressions. Without the colon operator, the filter for finding activities from 2022 would look like this:

'time>=d"2022-01-01 00:00:00"' 'time<=d"2022-12-31 23:59:59"'

With the colon operator and in conjunction with the virtual attribute year this expression becomes:

year:2022

... which should save some typing. The actual behaviour of the colon operator depends on the type of the field. The table below outlines its abilities.

Expression Used with fields of type Explanation
string string Matches if the lowercase string is contained in the field value
string list Matches if the lowercase string is contained as element in the list
int datetime Considered as year
int-int datetime Considered as year + month
int-int-int datetime Considered as year + month + day
int,int ... int Considered as list of numbers, matches if the field value is contained in the list
int..int int Considered as range of numbers, matches if the field value is within the range
int.. int Considered as range of numbers, with open end
..int int Considered as range of numbers, with open beginning
int-int-int..int-int-int datetime Considered as range of dates (missing month and day values are valid)
int-int-int.. datetime Considered as range of dates, with open end
..int-int-int datetime Considered as range of dates, with open beginning
\<empty> datetime Matches if the field value is empty

For examples see the examples section below.

Expressions

Expressions are the parts of filters against which the value of fields are compared. Depending on the type of the field, several expressions are valid (apart from the forms explained in the previous section about the colon operator).

Expression Explanation
bool may be \"true\" or \"false\"
int Treated as number
float Treated as number
string Treated as string, whitespaces need to be escaped with \"
iso date Treated a datetime, must comply to the isoformat and may need to be escaped

Filterless expressions and Keywords

As mentioned above, there are exceptions to the general form of filters, which save even more typing. In some cases the filter field and the operator can be omitted, which results in a certain predefined filter (\"filterless expression\"):

Filterless Expression Effect
int Is considered as activity id
2000..2023 Is considered as year of an activity (and overrules id from above!)

In addition, alphanumeric strings are considered keywords. Behind each keyword, there's a predefined filter, so the keyword can be used as a shortcut.

Keyword Filter Expression
afternoon time is between 13:00 and 18:00
bikecitizens origin is bikecitizens service
evening time is between 18:00 and 22:00
last7days time is within the last 7 days
last14days time is within the last 14 days
last30days time is within the last 30 days
last60days time is within the last 60 days
last90days time is within the last 90 days
lastweek time is within the last week
lastmonth time is within the last month
lastquarter time is within the last quarter
lastyear time is within the last year
morning time is between 06:00 and 11:00
night time is between 22:00 and 06:00
noon time is between 11:00 and 13:00
polar origin is polar service
strava origin is strava service
thisweek time is within the current week
thismonth time is within the current month
thisquarter time is within the current quarter
thisyear time is within the current year
today time is today
waze origin is waze

Examples

In order to get a notion of how filters work, here are a few examples, by using the list command.

Matches the activity with id = 100:

tracs list 100
tracs list id:100

Matches everything retrieved from Polar:

tracs list polar
tracs list classifier:polar
tracs list service:polar

Matches everything from June 2020:

tracs list date:2020-06

Matches everything from 2022:

tracs list 2022
tracs list year:2022
tracs list lastyear

Matches everything which has redbike as equipment and is tagged with race:

tracs list equipment:redbike tag:race

Matches everything from 2020 which misses a distance:

tracs list year:2020 distance:

Matches everything which happened last week in the morning where the average heartrate was between 160 and 180:

tracs list lastweek morning heartrate:160..180