I have a requirement I’d like to tack on, which may or may not be feasible, I’m not sure.
Background:
I have Book notes stored in /Sources/Books/<book_title>.md
In essence these are just filled with contents…
ie: ## Index ## chapter 1 … etc
In the front matter I also have a finished_date, which I fill in manually when I’m done reading.
In my daily notes I keep track of what I’m reading inline as:
Read:: [[book_title#chapter 1|Book Title]] | Chapter Name
This way in the book note, I can look up in the links for what I read, what specific chapters and when.
If helpful, my daily note also hold the tag #periodic/daily as well as linking to the current monthly note as [[YYYY-MM]]
Requirement:
In my monthly note, I’d like a table. to show which books I completed this month.
I’d got as far as:
TABLE Read as Completed
FROM [[2024-02]] and #periodic/daily
SORT file.name DESC
and feel WHERE contains(file.outlinks, link("XXX")) might be the filter I need, but how do I first filter down links from the books folder + check if the finished_date is not null and is in this month?
I’m a little uncertain if I understood all the details of your setup, but here is a query which might work:
```dataview
TABLE
FROM [[2024-02]] AND #periodic/daily
FLATTEN flat(list(Read)) as book
WHERE book.finished_date
AND dateformat(book.finished_date, "yyyy-MM") = dateformat(file.day, "yyyy-MM")
GROUP BY book
```
Let me try to explain the query, and hopefully this will give you enough information on how to do it correctly afterwards:
It starts out by doing the FROM [[2024-02]] and #periodic/daily which should give all daily notes linking to this particular monthly note
We then split up the list of books read from that daily note, using the special construct of flat(list(Read)) to ensure that even though you only read one book, it’s treated as a list of books, to make the following logic easier. This (enforced) list is then split into each book you’ve read
When then check if that book has a finished date, and whether that date has the same month as the daily note it came from (which should be 2024-02 in this case). ( And if you’re using Templater you could also set the right hand side directly to "2024-02" instead of doing the date format on the `file.day``
Finally we group on which books you’ve read, so as to just present one row for each book you’ve read
If it doesn’t work like this, try removing the GROUP BY on the end,
and change the first line to TABLE book, book.finished_date, file.day and let us know what the output of that query is.
Many other files in Sources/Books/ have the field either null or previous months/years.
Daily Notes
I have an entry for a chapter read like so:
Today
Read:: [[Sources/Books/Your Idea Machine#FIFTEEN PLACES TO FIND IDEAS|YIM - 15 Places to Find Ideas]]
Read:: [[Sources/Books/Your Idea Machine#Chapter 88|YIM - Last Chapter]]
Yesterday
Read:: [[Sources/Books/Your Idea Machine#INTRODUCTION|YIM - Intro]]
Read:: [[Sources/Books/Your Idea Machine#Chapter1|YIM - C1]]
Read:: [[Sources/Books/Your Idea Machine#INTRODUCTION|YIM - C2]]
Read:: [[Machines#INTRODUCTION|Machines - C3]]
Dataview
All Clear until here.
TABLE book, fd
FROM [[2024-02]] AND #periodic/daily/journal
FLATTEN flat(list(Read)) as book
FLATTEN dateformat(file.day, "yyyy-MM") as fd
Things then get tricky because links don’t always contain the folder, what I want it to do is go look up the book file and check if finish_read_date is present, valid, in this month.
I don’t think this is achieved by: WHERE dateformat(book.finish_read_date, "yyyy-MM") = fd
Where is the connection from your daily note to the monthly note? And what is the name of the daily notes?
You don’t need to do any of the stuff you mention since links are gathered into file.outlinks and file.inlinks.
It would be nice though if you had something in the book file which said it’s a book. Like type: book or tags: book. This would make a book file independent on is file location, which would be a good thing.
I see what threw me off in my previous response, and that is the fact you’ve defined your Read fields as texts consisting of :closed_book: and a link like [[Some book]] followed by the chapter specification | Chapter 3. This doesn’t make it easy to extract the link directly, as it’s treated by dataview as a pure text field.
In my world I think I would have just done this as:
And used a little custom styling so it displays like:
Oh well, I also see on closer inspection that all of your book reads are contained within lists, and that makes it possible to extract the outlinks of that list item. So the new game plan is then to do the following:
Find all daily notes from the current before using the same logic as before
Flatten all lists in those notes, and focus on those having a Read field
Assume there is only one link out of that item, and check whether that is a finished book
Group by the books, and present the results
```dataview
TABLE
FROM [[2024-03]] AND #periodic/daily/journal
FLATTEN file.lists as item
WHERE item.Read AND item.outlinks
FLATTEN item.outlinks[0] as book
WHERE dateformat(book.finished_read_date, "yyyy-MM") = dateformat(file.day, "yyyy-MM")
GROUP BY book
```
The above query do deliver the goods, at least in my test cases, but the important question though is why do we bother to go through which books you’ve read or not in the daily notes? You’ve already tagged the books themselves with the finished date, so why not go directly to the source?
```dataview
LIST
FROM #library/book OR #library/audiobook
WHERE finished_read_date
AND dateformat(finished_read_date, "yyyy-MM") = this.file.name
```
If you put that in the montly note, you’ll get the result directly without no intermediate round trip through the daily notes.