# Facet JSON Structure¶

## Structure¶

The overall structure of filters is as follows. Each facet term combines a data source and constraint spec, and so all combinations of constraint kind and data source path are possible in the syntax.

<FILTERS>:  { <logical-operator>: <TERMSET> }

<TERMSET>: '[' <TERM> [, <TERM>]* ']'

<TERM>:     { <logical-operator>: <TERMSET> }
or
{ "source": <data-source>, <constraint(s)>, <extra-attribute(s)> }


In the following sections each of location operators, data source, constraints, and extra attributes are explained. You can also find some examples at the end of this document.

## Logical operators¶

We want the structure to be as general as possible, so we don’t need to redesign the whole structure when we need to support more complex queries. Therefore as the top level, we have logical operators.

{ "and": [ term... ] }
{ "or": [ term... ]}
{ "not": term }


## Data Source¶

The difference between base table columns and columns in related entities is just a difference in data source. It shouldn’t involve a completely different set of filter structures. Instead, the single filter structure should conceptually allow various forms of data source specification

"*"
"Column1"
[{"inbound": ["S1", "FK1"]}, "Column2"]
[{"inbound": ["S1", "FK1"]}, {"outbound": ["S2", "FK2"]}, "Column3"]


The simple form "Column1" might be allowed as a short-hand for ["Column1"] since it isn’t ambiguous. But any foreign key path also needs to end with the actual column that will be projected and filtered. The direction field labels "inbound" and "outbound" remove any ambiguity for self-referencing table navigation scenarios. The constraint name pairs ["S1", "FK1"] etc. reuse the same names appearing in the ERMrest model introspection document.

Even if we are faceting on a vocabulary concept and just want the user to pick values by displayed row name and we substitute the actual entity keys in the ERMrest query, we must record this column choice explicitly in the facet spec, e.g. [{"inbound": ["S1", "Fk1"]}, "id"] so that the resulting faceting app URL is unambiguous even if there have been subtle model changes in the interim, which might change the default key selection heuristics etc.

Based on this, we are not supporting filtering on foreign keys with composite keys.

### Specific occurrences of rows¶

If we ever need to model a set of constraints where the same related entity row must simultaneously satisfy multiple facet constraints, we could add these optional instance identifier to the path elements: