Using dataview to display mentions of upcoming dates in my daily pages?

Example:

I’ll write in my daily note today—

2025-02-08

  • Talked to [[Mom]]
    • she has an appointment on [[2025-08-11]]

and then, when I open my daily note on Monday, 2025-08-04, I want to see a list of upcoming mentions for the week, including

  • Talked to [[Mom]]
    • she has an appointment on [[2025-08-11]]

Is it possible (with dataview and/or templater?) to

  1. display mentions on a rolling-date basis?
  2. display these mentions with their surrounding context?

It’s doable, but I’m not sure how easy or robust such a query would be. Especially, when you got the date in a sublist of the item I’m reckoning you actually want to list.

Basically your query would then need to:

  • Look at every list item which are having children. For each of those children:
    • Look at any outlinks of that child, and check if it’s a date link of the upcoming week
    • If it matches, return the entry

If in addition you want to only list that child, it gets even hairier…

The road towards the final query

Put the following in a file in your vault, and replace the FROM "..." part with the full exact path to this file.

---
Tags: f96355
---
questionUrl:: http://forum.obsidian.md/t//96355

- Talked to [[Mom]]
    - Has an appointment on [[2025-02-11]] with [[John Doe]]
    - Doesn't have anything to do with [[somewhere]] or [[Someone]]
- Talked to [[Dad]]
    - Had an appointment yesterday, that is [[Journal/2025/02/2025-02-07]]
    - And another one on [[2025-02-16]]
- Talked to someone uninteresting
- Didn't even talk to this guy
    - But he was surely uninteresting
- Wow, post this query
    - Explain this query on  [[2025-02-08]]
    
## Base query

```dataview
TABLE WITHOUT ID
  item.text as "Text", length(item.children) as "Child count" 
FROM "ForumStuff/f96/f96355/t96355 test 2025-02-08.md"
FLATTEN file.lists as item
```


## Limit down to items with children and outlinks

```dataview
TABLE WITHOUT ID
  item.text as "Text", length(item.children) as "Child count", candidates as "Outlink candidates"
  , map(candidates, (m) => meta(m)) as "meta on outlinks"
  , map(candidates, (m) => m.file.name) as "existing file names"
  , flat(map(candidates, (m) => slice(split(meta(m).path, "/"), -1))) as "split path"
FROM "ForumStuff/f96/f96355/t96355 test 2025-02-08.md"
FLATTEN file.lists as item
WHERE length(item.children) > 0 
  AND any(item.children.outlinks)
FLATTEN list(flat(item.children.outlinks)) as candidates
```

## The  query with date (as string) checks

```dataview
TABLE WITHOUT ID
  item.text as "Text", length(item.children) as "Child count", candidates as "Outlink candidates"
  , candidateFiles
  , currentDay, aWeekFromNow
  , (map(candidateFiles, (c) => c >= currentDay AND c <= aWeekFromNow)) as "candidate checks"
  , (map(candidateFiles, (c) => c >= currentDay )) as "after today"
  , (map(candidateFiles, (c) => c <= aWeekFromNow )) as "before a week"
FROM "ForumStuff/f96/f96355/t96355 test 2025-02-08.md"
FLATTEN file.lists as item
WHERE length(item.children) > 0 
  AND any(item.children.outlinks)
FLATTEN list(flat(item.children.outlinks)) as candidates
FLATTEN string(file.day) as currentDay
FLATTEN string(file.day + dur(7 days)) as aWeekFromNow
FLATTEN list(flat(map(candidates, (m) => slice(split(meta(m).path, "/"), -1)))) as candidateFiles
```


## The final query

```dataview
TABLE WITHOUT ID item.text as "Text", relevantChilds.text as "Child text"
FROM "ForumStuff/f96/f96355/t96355 test 2025-02-08.md"
FLATTEN file.lists as item
WHERE length(item.children) > 0 
  AND any(item.children.outlinks)
FLATTEN list(flat(item.children.outlinks)) as candidates
FLATTEN string(file.day) as currentDay
FLATTEN string(file.day + dur(7 days)) as aWeekFromNow
FLATTEN list(flat(map(candidates, (m) => slice(split(meta(m).path, "/"), -1)))) as candidateFiles
WHERE any(map(candidateFiles, (c) => c >= currentDay AND c <= aWeekFromNow))
FLATTEN list(filter(item.children, 
  (child) => any(map( child.outlinks, (ol) => slice(split(meta(ol).path, "/"), -1)[0] >= currentDay AND slice(split(meta(ol).path, "/"), -1)[0] <= aWeekFromNow)))) as relevantChilds
```

The final query repeated again:

```dataview
TABLE WITHOUT ID item.text as "Text", relevantChilds.text as "Child text"
FROM "ForumStuff/f96/f96355/t96355 test 2025-02-08.md"
FLATTEN file.lists as item
WHERE length(item.children) > 0 
  AND any(item.children.outlinks)
FLATTEN list(flat(item.children.outlinks)) as candidates
FLATTEN string(file.day) as currentDay
FLATTEN string(file.day + dur(7 days)) as aWeekFromNow
FLATTEN list(flat(map(candidates, (m) => slice(split(meta(m).path, "/"), -1)))) as candidateFiles
WHERE any(map(candidateFiles, (c) => c >= currentDay AND c <= aWeekFromNow))
FLATTEN list(filter(item.children, 
  (child) => any(map( child.outlinks, (ol) => slice(split(meta(ol).path, "/"), -1)[0] >= currentDay AND slice(split(meta(ol).path, "/"), -1)[0] <= aWeekFromNow)))) as relevantChilds
```

First of all the FROM "full/file/path/to/date-note.md" needs to match your daily note name, and I do use file.day later on to get the date from this file. You could use WHERE file = this.file instead, at the risk of scanning the full file list of your vault each time you run either of the queries.

The different FLATTEN’s down the line do the following:

  • file.lists as item - Splits up any lists into their seperate item’s
  • list(flat(item.children.outlinks)) as candidates – This hefty line pulls all the links out of any child item to the current item, and stores them into another list (instead of splitting up the query into multiple rows) namely the candidates list
  • string(file.day) and the next – Stores away the currentDay, and the date aWeekFromNow
  • the ugly one as candidateFiles – For each of the candidates, split the path of it into folder parts, and keep only the last part (using slice(..., -1). This list is flattened to reduce list levels, and stored as a list in the variable (See detail queries for some variant leading up to this ugly beast)
  • Given the variables we’ve built, it’s now a (relatively :smiley: ) easy WHERE clause to check if any of the candidates is within the date range
  • Another ugly one as relevantChilds – If you need to see the line with the date (or whatever), we need to redo the logic to split out the relevant child repeating most of the logic, but now all done in one ugly beast of a statement

So there you have it, a query pulling the appointment line of upcoming dates from your daily pages. In the test file, the final query returns:

Whether this has been explained reasonably, or not, or even if it’s usable in your case, that remains to be seen.

1 Like

I am blown away by your in-depth response and elaborate query solution! :bowing_woman:

I’m testing it now and stuck already at the first FROM. When I replace your path with “Journal/2025-02-10.md” as you instructed, it produces an empty table. When I broaden the path to my folder “Journal”, it populates a table with listings of every date mention in my daily notes since the beginning of time, not filtered to the next 7 days.

I’m completely out of my element at this level of querying, so my own troubleshooting efforts have been limited.

I don’t want to take more of your time, but I’d love to buy you a cup (pot?) of coffee for all this if we could get it working.

Many thanks to you either way.

Are you not able to get reproduce the query results of the test queries? Or is it just failing when you start adapting it to your vault?

1 Like

I was adapting to my vault, I had not attempted the test queries as you suggested (I missed that note).

Now I’m testing per your exact instructions (▼ The road towards the final query)

I replaced the FROM path (in all four queries) as follows: FROM "Journal/test-journal-doc.md"

The first two queries are working beautifully :ok_hand:

The last two queries are producing this same error message:

Dataview: Every row during operation 'flatten' failed with an error; first 3:

                - No implementation found for 'null + duration'
- No implementation found for 'null + duration'
- No implementation found for 'null + duration'

So there is something not being set since it’s trying to add a null value and a duration. I assumed that you’ve got the date in your daily note title. What do you use as a file name for your daily notes? If it doesn’t have “YYYY-MM-DD” somewhere, the queries will fail as they stand now.

If that’s the case, you can either change the file name, add a date property with the correct date, or change the query parts related to file.day. All depends on what you call your daily notes, and if you’ve got the date readily available somewhere in your daily notes.

I apologize, I overlooked that detail.

Okay now I’ve got it working perfectly in all four of your test queries (after renaming my test note with today’s date, which is how all my daily notes are named). :pray:

However, while this works great to query date mentions within one single note, my objective was to query all my daily notes for any date mentions within the timeframe of 7 days from today.

Is this possible?

EDIT:
I stored this test note in the folder with all my real daily notes (with YYYY-MM-DD doc names) and it’s not retrieving any date mentions from any other note, it’s only showing me the date mentions from inside the test note.

I’m not sure how expensive such a query would be, but in theory the only change needed should be to change the FROM "my/journal/path/a daily note 2025-02-10.md" to FROM "my/journal/path". This would change the query to focus the on all files in that folder, instead of one specific file.

You should also be able to change or replace the FROM with a combination of FROM and WHERE if you so like. That would allow you to filter out the daily notes where you’d want to do this test.

Yes I’ve already tried this—in my first response to you, I mentioned that broadening the FROM to the folder (“Journal” instead of “Journal/2025-02-11 test.md”) populates the table with all date mentions (across years, past and future) without filtering them to the next 7 days.

I think the query is taking the file name from “FROM” and flattening that into the string “currentDay”, and filtering by this date. When it’s using today’s daily note in “FROM”, then “currentDay” is today; but when it’s using my whole folder of daily notes, the “currentDay” becomes everyday… ?

I fixed it by replacing file.day with date(today) :+1: now it’s filtering correctly.

Final Query

TABLE WITHOUT ID item.text as "Text", relevantChilds.text as "Child text"
FROM "Journal"
FLATTEN file.lists as item
WHERE length(item.children) > 0 
  AND any(item.children.outlinks)
FLATTEN list(flat(item.children.outlinks)) as candidates
FLATTEN string(date(today)) as currentDay
FLATTEN string(date(today) + dur(7 days)) as aWeekFromNow
FLATTEN list(flat(map(candidates, (m) => slice(split(meta(m).path, "/"), -1)))) as candidateFiles
WHERE any(map(candidateFiles, (c) => c >= currentDay AND c <= aWeekFromNow))
FLATTEN list(filter(item.children, 
  (child) => any(map( child.outlinks, (ol) => slice(split(meta(ol).path, "/"), -1)[0] >= currentDay AND slice(split(meta(ol).path, "/"), -1)[0] <= aWeekFromNow)))) as relevantChilds

I’d love to sort these listings by the date mentions, but I’m just thrilled to have this working at all :pray:

Using date(today) will not be relative to the date of where the query resides, or the daily note you’re looking at. It’ll always refer to today. If that’s what you want, then you’re set.

If you want to pick up the date from the note, and view appointments relative to the date of that particular daily note, you’ll need to somehow get that date from the file metadata. Which I tried to do using file.day, in which it would pick the date from the current daily note.

I see the usefulness of picking the date from the current note, however using file.day breaks the filter (when broadening the “FROM” to an entire folder of daily notes).

Maybe there’s another way to grab the date from the current file, I’ll look into it.

FWIW — this.file.day did the trick (tested and confirmed).

1 Like