Template (Dataview) to embed all headings (blocks) that contain keyword from a list

Why

First I want to explain why I’m doing this, because I can imagine someone already found clever solutions for my problem.
I started using daily notes, and while in the beginning I was still creating subject/project specific notes for each topic that was longer than a few lines and linked / embedded those in my daily notes, I soon noticed that this was too much effort, and on busy days I either would miss some topics, or just write the headings into my daily notes and not transfer them.

The plan

I want to create a template in which

  • I first create a list of keywords (Inline yaml or so?)
  • then I create a query that is searching through my daily notes (folder) for headings containing these keywords, and then I list or embed all those blocks sorted by date

Which should give me basically a full list of what I noted for a specific project/topic in a chronological order. And since I would’ve embedded a seperate note (file) into the daily note, those would also be part.

Is this possible? - Surely.

I see the biggest issue in the dynamic list. Which means I probably need to use dataview(js)?

Keywords

this should be the easiest part
add a list of words to the frontmatter:

keywords: [apple, banana, strawberry, lemon]

Call to keywords

Works in both dataview and dataviewjs:
=this.keywords
$=dv.current().keywords

Filter

Filter for dailies

dv.page('"Daily_Folder"')

But that is all I manage to do, …

Filter for headings

I can’t even remember having seen that in the snippets yet, is it possible?

Filter content for keywords

For this as well how would I compare for a list of words? - Especially since I dont want to compare all pages with the 1st and then alll pages with the 2nd keyword. Unless I could sort them again afterwards

Embed via DV

Is it possible to embed blocks via dv ?

Sort via date

since my daily notes are named like YYYY-MM-DD this should be possible to handle via
sort(p => .file.link) or similar

Alternatives?

Any alternative workflows?
Alternative plugin choices?

Before diving into the dataview questions, a quick big-picture question: have you looked at using Obsidian’s search feature for this? You can embed queries as dynamic code blocks, like dataview, and I think you can search headings/sections/blocks. Pinging @CawlinTeffid as someone who knows more about embedding search queries.

1 Like

This embedded search should create a list:

```query
path:(Daily Notes Folder/) ("# apple" OR "# banana" OR "# strawberry" or "# lemon")
```

The single hash will pick up an heading level (because all of them end with one). I’m not sure what the default order is. If it’s by name then that gives you date order (assuming the notes are named by date).

For more control over how the results are displayed (the same options that search in the side pane has), you could try the Query Control plugin. It’s in beta, not yet in Community Plugins.

3 Likes

I’ll look further into queries, thx a lot!

Things that come to midn right away:

  • how to get the keywords from the metadata into the query (for templating)
  • how to handle the keyword not being the first word after #
  • how to handle lower/uppercase

I looked into the queries and the plugin, and came up with this:

path:(00_Daily/) section: ignore-case: ("apple" OR "banana" OR "strawberry" or "lemon") # how to chain/nest these queries isn't documented well, but this seems to work
# 'section' searches for sections so between 2 headings, which might let me omit the # to only search headings, and definitely avoids too many search results
# 'ignore-case' so I dont have to worry about it
collapsed: true
context: true
hideTitle: true
sort: alphabeticalReverse #all of those are from the plugin, and rather self explaining, most important I found 'hideTitle' and 'context'

Querying for sections seems like it embeds the full full section if I choose the more context option, but I need to test more.

Still open is, whether / how I could take keywords from the frontmatter and use them automagically as words inside the query. Any ideas?

1 Like

You mentioned in your first post in the thread that you are doing this inside a template. Are the keywords common across the template or will you be setting them per-file? Also: what do you use for inserting your templates? (Obsidian core Templates plugin, community Templater plugin, something else…)

If you want different keywords each time you use the template, I’d just put placeholders and replace them manually when you use the template. If you want the same ones each time, just put them directly in the template.

Regular expression: /# .*keyword/ (the slashes tell Obsidian to treat the part between them as a regular expression, the . means any character, and the * means “0 or more of the preceding item”).

Obsidian’s search is case-insensitive by default.

2 Likes

I think you don’t need ignore-case by default.

I’m not checking the documentation, but I think collapsed: true and context: true contradict each other. Altho that setup probably makes sense if you want the results to start collapsed and show more than default context when you open them.

1 Like

You mentioned in your first post in the thread that you are doing this inside a template. Are the keywords common across the template or will you be setting them per-file? Also: what do you use for inserting your templates? (Obsidian core Templates plugin, community Templater plugin, something else…)

Ah yeah, I want to set the keyword per file, and I thought it would be easier to type a list in the frontmatter, than inputting the keywords in between “” and OR and other expressions.

For now I’m using the core Templates plugin, but I’m always willing to try something new (as long as it doesnt break too much old stuff :D).

In this case I’d create a new note, insert frontmatter, type the keywords and only then (or maybe after a few weeks) I’d insert the template for the search query.
So the keywords would be already there, when the template is being evaluated.

So with templater I’d probably have to write a script that takes the list (array?) from my frontmatter (<% tp.frontmatter.keywords%> as
argument, splits it up on commata, optionally trims, and then joins it together as
(" /# .*keyword[0]/" OR " /# .*keyword/[1]"... OR "/# .*keyword[n]/" ) which is placed in the first line of my query as <% tp.user.keywordqry(tp.frontmatter.keywords) %>

Sounds possible, time to learn a bit JavaScript :smiley:

Regular expression: /# .*keyword/ (the slashes tell Obsidian to treat the part between them as a regular expression, the . means any character, and the * means “0 or more of the preceding item”).

Nice! That gives me both options, I’ll keep them in commentary so I remember.

I’m not checking the documentation, but I think collapsed: true and context: true contradict each other. Altho that setup probably makes sense if you want the results to start collapsed and show more than default context when you open them.

Yes I tested them, and found this to be useful. One click and maximum information.

You could copy-paste the keywords into the expression and use the Apply Patterns plugin to turn each space into " OR " (or you could use the core find-replace but you’d have to type the pattern each time). It’s more work in the moment but doesn’t require you to learn JavaScript.

Or I’ll use it UNTIL I learn javascript :slight_smile: (probably never then)
Ty. That is some satisfactory solution.

Yeah that works pretty well, I can define multiple search/replace rules per pattern.

  1. I replace the comma seperated words with the key for regexp search, the word space OR *space : (\w+)(,? ?)"/.*$1/" OR
  2. I replace the opening square bracket with an opening parenthesis (\[)(
  3. I replace the last OR with the closing bracket with just the closing paranthesis (OR \]))

PS: don’t forget to turn on g modifier

I only have to copy&paste and mark it. Although I could skip writing it into the frontmatter right now… only if I create the keywords just before the query though. I could also create a pattern to turn the modified keywords into the full query.
Endless possibilities :smiley:

2 Likes