Creating a Related section with Dataview


I’m fairly new to obsidian, been copying a lot of Nick Milo stuff, using his template and his it.

I like his notes templates, but I also use a “related” section at the end of my notes. I usually put them manually, but would like to create an automatic related dataview that brings all pages with the same hastags as the one I am writing.

For example if I hear a morning routine from someone I’s like to tag it as
#Topic/morning routine
and then at the end, the related table will have all morning routines.

The problem is if my page has one tag, it works if it has 2 hashtags it won’t. I use it in template for all new notes, so I need it to work with multiple hashtags in one page.

Things I have tried

this works with one hashtag

 file.tags as "Tags"

WHERE any(contains(file.tags,[[]].tags))

SORT asc

What I’m trying to do

If a page has for example #topic/morningroutine and #People/RobinSharma the table at the end will have all pages that are tagged with either.


Ok so now I got it to kind of work:

 tags as "Tags"

WHERE contains(tags,[[]].tags)

SORT asc

this finds notes that include ALL tags, but I would like to have all notes that have one tag OR the other.

For example if it has #morningroutine and #robinsharma it finds notes that have both, but won’t find notes with #morningroutine only.

anyone have any idea?

So here are two queries. The first is just to show my test data set, and the second shows the actual result. Note that first file in the first result set is the one I want to match against and where the query is run. In other words, it’s looking for any combination of #topic/morningroutine or #people/RobinSharma.

LIST file.etags
FROM #f53315 or "ForumStuff/f53315/f53315 multi-tag to multi-tag"

  join(file.etags) as Etags,
  join(tagmatches) as Matches
FROM #f53315 
FLATTEN list(filter(file.etags,
  (t) => econtains(this.file.etags, t))) as tagmatches
WHERE length(tagmatches) > 0

And this produces the following output for me:

The crucial part of this query

FLATTEN list(filter(file.etags,
  (t) => econtains(this.file.etags, t))) as tagmatches
WHERE length(tagmatches) > 0

Here I compute the list of matching tags, and this is done in multiple steps:

  • list( ... ) as tagmatches – This stores the end result of the filter into a new list. You don’t need to present this list in the end result, but it is needed for the where to function later on
  • filter(file.etags, (t) => ... ) – This splits up file.etags into its separate tags, t, and if the following expression, ..., returns a positive value, this tag is included in the end result
  • econtains(this.file.etags, t) – This expression checks whether the t is fully contained (using econtains) in this files (complete) tags (using this.file.etags)
  • WHERE length(tagmatches) > 0 – If the filter had positive matches, which are then collated into the list, and stored in tagmatches, we here check if that list has any elements. If you wanted it to have at least 2 matches, you could change it to >= 2, and so on.

Use of file.etags vs file.tags

I’m using file.etags to get to the entire tag here, and not just file.tags which I see a lot of people use in various contexts. If I change the query to use file.tags in all the places I originally used file.etags, I’ll get this output:

See how in the second column the nested tags are split up into their separate parts? This also cause the None of the above file to be included in the results since it has a nested tag starting with #topic and a nested tag starting with #people although the end of both those tags are different to the matching tags of the current file. Also in the tagmatches columns you notice that the top level of the nested tags are included.

This can be useful in some circumstances, but it could also ruin your query in other circumstances. So choose wisely depending on your use case.


Thanks! you are a hero, I actually modified it because my files have tags:: as the template and it wasn’t working if I didn’t modify it, but found to avoid the partial tag, i only had to keep etag in the filter part. So ended up like so

join(tagmatches) as Matches,
join(tags) as Tags

FLATTEN list(filter(file.etags, (t) => econtains([[]].tags, t))) as tagmatches WHERE length(tagmatches) > 0

I’m a newbie so I really have no idea what you did there, but appreciate it.
Question is there a way to also add files mentioned? I mean also include [[This page]] wich is mentioned within the text?

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.