Filters – Project Haystack

Filters

OverviewUsageArrow OperatorRef ListsGrammar

Overview

Filters are a simple declarative language used to query Haystack data. A filter is a predicate function which takes a dict and returns true/false (match/no match). Some filter constructs require the use of defs in which case the filter must be evaluated in the context of a namespace.

Usage

The simplest filter is just a tag name which matches any record which contains that tag (regardless of its value):

site  // query any record with the "site" tag

To match a tag value you can use any of the equality or comparison operators:

geoPostalCode == "23220"   // equal to
geoPostalCode != "23220"   // not equal to
curVal < 75                // less than
curVal <= 75               // less than or equal to
curVal > 75                // greater than
curVal >= 75               // greater than or equal to

The scalars to compare against are encoded using Zinc encoding (with couple exceptions noted below).

You can combine filters using and, or, or not:

site or equip             // has site or equip tag
equip and hvac            // has equip and hvac tag
equip and not ahu         // has equip tag, but not the ahu tag

Arrow Operator

You use the -> operator to dereference a tag which has a Ref value. For example if your equip rec has a siteRef tag that references the site, you can query for equip in a given city such as:

equip and siteRef->geoCity == "Chicago"

The way to read the above expression is match an entity if:

  • it has equip tag
  • and it has a siteRef tag which is a Ref
  • and what the siteRef tag points to has the geoCity tag
  • and that the site's geoCity tag is equal to "Chicago"

The arrow operator may also be used if the tag value is a nested Dict.

Ref Lists

Haystack allows a list of refs to be used for relationships where a single ref might be used. When a tag value is configured as a list of refs, then a filter will match if any one of the refs match.

Consider an example with a VAV which has an airRef configured with as list of two refs:

// records
id:@ahu1, dis:"AHU-1", ahu, equip
id:@ahu2, dis:"AHU-2", ahu, equip
id:@vav, airRef:[@ahu1, @ahu2], vav, equip

// all of these filters will match the VAV record
airRef == @ahu1
airRef == @ahu2
airRef->dis == "AHU-1"
airRef->dis == "AHU-2"

Note that pathing through a list of refs using "->" will check the path on each ref recursively.

This technique should never be used for the fundamental containment tags siteRef, equipRef, or spaceRef.

Grammar

The formal grammar of the filter langauge:

<filter>     :=  <condOr>
<condOr>     :=  <condAnd> ("or" <condAnd>)*
<condAnd>    :=  <term> ("and" <term>)*
<term>       :=  <parens> | <has> | <missing> | <cmp>
<parens>     :=  "(" <filter> ")"
<has>        :=  <path>
<missing>    :=  "not" <path>
<cmp>        :=  <path> <cmpOp> <val>
<cmpOp>      :=  "==" | "!=" | "<" | "<=" | ">" | ">="
<path>       :=  <name> ("->" <name>)*

<val>        :=  <bool> | <ref> | <str> | <uri> |
                 <number> | <date> | <time>
<bool>       := "true" or "false"
<number>     := same as Zinc (keywords not supported INF, -INF, NaN)
<ref>        := same as Zinc
<symbol>     := same as Zinc
<str>        := same as Zinc
<uri>        := same as Zinc
<date>       := same as Zinc
<time>       := same as Zinc
<name>       := same as Zinc <id>

See Zinc grammar for productions reused from Zinc. Bools are encoded as "true" or "false" (Zinc encodes as "T" or "F").