24 Filters

A filter keeps the current values for which a condition is true. In relational-model terms, filtering is the restriction operation inside a path expression.

The following path reaches the advanced courses in the university:


u.course.[advanced]

The filter is applied to the current courses. After the filter, the path still contains courses, just fewer of them.

The path tail advanced is evaluated as C.advanced(A), and the filter condition itself becomes the conjunct A in the frame:


course=C:Course
where
  ∃A:Boolean
    u.course(C)
  ∧ C.advanced(A)
  ∧ A

Navigation can continue from the filtered courses in the usual way.


u.course.[advanced].code
u.course.[advanced].department.name

Filters can use ordinary comparisons. This expression reaches the enrolments whose mark is at least 50:


u.enrolment.[mark ≥ 50]

A filter can appear after navigation. In the next expression, the path first reaches each student's enrolments, then keeps only current enrolments, then reaches the corresponding course codes.


u.student.enrolment.[current].course.code

The position of the filter matters. A filter applies to the values reached at that point in the path. Here [advanced] applies to courses:


u.student.enrolment.course.[advanced].code

Here [current] applies to enrolments:


u.student.enrolment.[current].course.code

Path tails inside filters

In general, filter conditions are logic formulas whose terms are path tails. This is powerful because filtering composes with navigation, folds and the other forms of path expression.

For example, this path reaches courses offered by the mathematics department:


u.course.[department.name = "Mathematics"].code

Attributes are reached one value at a time

An attribute is used as a value of its declared type. Its cardinality says how many values may be reached; it does not turn each reached value into a set.

For example, name has type String, so this is a type error:


u.department.[name ⊆ {"Mathematics", "Physics"}]

The operator ⊆ compares sets. The path tail name reaches strings, so membership is the right test:


u.department.[name ∈ {"Mathematics", "Physics"}]

The same rule would apply if an entity could have several names. Each reached name would still be a String, so the filter would still use ∈, not ⊆. This mistake often appears with ⊂, ⊃, ⊆, ⊇, ⊄ and ⊅ in filters and constraints.

Using richer logic formulas in filters

A filter condition can be more substantial. This expression reaches current enrolments in advanced mathematics courses where the student has not already completed the course and either has a passing mark or no mark has been recorded:


u.enrolment.[
    current
    ∧ course.advanced
    ∧ course.department.name = "Mathematics"
    ∧ course ∉ student.completed.Σ
    ∧ (mark ≥ 50 ∨ mark = none)
]

The condition inside a filter is a Boolean-valued path expression evaluated in the current path context. It may itself contain path tails, such as course.department.name and student.completed.Σ above. Existing knowledge about writing Boolean expressions still applies. For example:

Kind Examples
Comparisons =, ≠, <, >, ≤, ≥
Set and membership tests ⊂, ⊃, ⊆, ⊇, ⊄, ⊅, ∈, ∉
Logical connectives →, ←, ↔, ∧, ∨, ¬
Boolean-valued functions User-defined predicates and Boolean-valued functions