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 |