Use case
Many vaults use a parents multitext property to build hierarchies — projects with sub-projects, places with sub-places, org charts, etc:
# Project A (root)
parents: []
# Project B (child of A)
parents: "[[Project A]]"
# Project C (grandchild — child of B)
parents: "[[Project B]]"
In a Bases view embedded in Project A, I want to see all descendants — not just direct children, but grandchildren, great-grandchildren, etc.
What works today
Direct children (one level deep):
filters:
and:
- parents.contains(this.file.name)
This works perfectly. It returns all notes where parents includes the current note’s name.
What doesn’t work
Any attempt at recursive filtering fails because you can’t access frontmatter properties from within a filter() chain.
Attempt 1 — traverse via file.links
# Degree 2: grandchildren
file.links.filter(value.asFile().parents.contains(this.file.name)).length > 0
Error: Cannot find parents on type File — asFile() returns a File object which doesn’t expose frontmatter properties like parents.
Attempt 2 — traverse via parents directly
parents.filter(value.asFile().parents.contains(this.file.name)).length > 0
Fails silently — multitext property values don’t support asFile() resolution.
Attempt 3 — use the result of one filter as input to another
parents.containsAny(parents.contains(this.file.name))
Doesn’t work — parents.contains() returns a boolean, not a list of matching notes. There’s no way to capture “the set of notes matching filter X” and feed it into filter Y.
The gap
The filter engine already evaluates parents.contains(this.file.name) across every note in the base — it knows which notes are direct children at evaluation time. But it discards that intermediate result. If it could expose that result set as a reusable list, recursive hierarchies would work:
# Pseudocode for what would solve this
filters:
or:
- parents.contains(this.file.name) # direct children
- parents.containsAny(matchingNames(parents.contains(this.file.name))) # grandchildren
Or equivalently, if asFile() could access frontmatter:
# If this worked, recursion would be straightforward
file.links.filter(value.asFile().note.parents.contains(this.file.name)).length > 0
Proposed solution
-
containsTransitive(property, value)— a built-in that walks a named property chain recursively. E.g.parents.containsTransitive(this.file.name)returns true ifthisappears anywhere in the ancestor chain viaparents -
Expose frontmatter from
asFile()— letvalue.asFile().propertyNameorvalue.asFile().frontmatter.propertyNameaccess note properties. This would make the degree-2+ filters work with the existingfilter()syntax -
Result-set reuse — let a filter expression return the set of matching file names (not just a boolean), so it can be used as input to
containsAny()or similar
Option 1 is the most user-friendly. Option 2 is the most general (enables many other use cases). Option 3 is the most flexible but potentially complex to implement.
Why this matters
Parent-child hierarchies are one of the most common structures in personal knowledge management:
-
Project management — projects → sub-projects → tasks (my use case — ~70 project notes, 3 levels deep)
-
Places — country → city → building → room
-
Organisations — company → department → team
-
Academic notes — topic → subtopic → concept
Currently, Bases can only show one level of these hierarchies. Showing the full tree requires Dataview — which undermines the value of Bases as a native, no-plugin solution.
Environment
-
Obsidian 1.8.x
-
Bases (core plugin, latest)
-
macOS / iOS