"include" in DataviewJS to limit selection of files to current year

Continuing the discussion from Simple include in dataviewjs not working:

I have a book database, one note per book, and a Stats page that includes things like

dv.paragraph("# Since 2020, I've read " + BookCount + " books")

where BookCount is

let BookCount = (dv.pages('"Book Log"').where(p => p.Medium == "Book" || p.Medium == "eBook").length);

Now I’d like to add a dv.paragraph that describes books read this year. The book note frontmatter includes a variable DateFinished: followed by the date so e.g.
DateFinished: 2023-01-30

I’d like to have a dv.paragraph that goes something like

dv.paragraph("This year, I've read " + BooksThisYear + " books.")

I have a year function:

let year = DateTime.now().toFormat("yyyy");

and I’m trying to implement that:

let BooksThisYear = dv.pages('"Book Log"').where(p => p.DateFinished.includes(year));

The reason I’d like it to be dynamic, i.e. that it include(year) instead of include("2023") (which also doesn’t work btw) is so that next year I won’t have to go through the code to change everything to 2024. I guess I’m lazy like that haha.

Any advice?
Thanks!

Without testing, I’m thinking something like the following should work:

```dataviewjs
let BooksThisYear = dv.pages('"Book Log"')
  .where(p => p.DateFinished.toFormat("yyyy") == year);
```

If you don’t want to be bothered going by the format option, you could also do something like:

```dataviewjs
const year = DateTime.now().year
let BooksThisYear = dv.pages('"Book Log"')
  .where(p => p.DateFinished.year == year);
```
Bonus tip: How to present code properly in a forum post

If you want to showcase either markdown, or code blocks, or dataview queries properly in a forum post, be sure to add one line before and one life after what you want to present with four backticks, ````. This will ensure that any other backticks (like for code blocks) is properly shown.

Thanks, I’ve updated the post. In the preview my code lines were all single lines, so I thought it would look all right, but in the post itself it went into multiple lines.

As for your solutions: Neither work, unfortunately.

For the first thing, I get

Cannot read properties of null (reading 'toFormat')

For the const thing, I get

Cannot read properties of null (reading 'year')

Any ideas?

Btw. will this work with my date formats? I use YYYY-MM-DD

Thanks :slight_smile:

I’m a little tired, and made the same mistaken in both queries. If you do p.DateFinished.something in a where clause when DateFinished is not present, it’ll fail with that message.

You need to do p.DateFinished?.something, or more specific either do the p.DateFinished.toFormat("yyyy") in the first query, or p.DateFinished?.year in the second query. Then both should work.

The extra question mark, ?, allows javascript to bail out gracefully, if the preceding field is not present in any of your files.

As long as the dates are proper dates, and not just strings, it should work, yes. And YYYY-MM-DD should be parsed by dataview(/js) as a proper date (in most cases).

1 Like

All right, I think we’re getting somewhere.

I’ve now got:

 let year = DateTime.now().toFormat("yyyy");
 let BooksThisYear = dv.pages('"Book Log"').where(p => p.DateFinished?.toFormat("yyyy") == year);

dv.paragraph("# This year (" + year + ") I've read " + BooksThisYear + " books.")

I’m not getting an error, but this is the output:

That’s a link but it just creates a note named object Object] etc.

Any ideas?
Thanks :slight_smile:

Yeah, you’re listing the entire page object, not the name, nor the link, nor any of the other stuff available from a page. So if you want a list of the names, instead of BooksThisYear, do BooksThisYear.file.name.join(", "),
and similar use file.link if you want links to the books. (This is within the dv.paragraph() context)

The .join(", ") is kind of superfluous, but if I don’t add it I sometimes to get an extra ] at the end, and I’m not quite sure why. So I tend to add it, to be on the safe side.

Tinkering along with you guys. This worked for me:

let year = DateTime.now().year
let BooksThisYear = dv.pages('"Book Log"')
	.where(p => p.datefinished.year == year).length

dv.paragraph("This year, I've read " + BooksThisYear + " books.")

Adding .length seemed to return the number of books instead of the books objects. Was that your intention?

1 Like

He’s asking two questions, and the first one regarding the number of books he got covered, so that was his intention, but he had some issues related to getting the list of books.

Do note, that in your query you’re missing the datefinished?.year, which most likely works for you because every file in your test set up has the datefinished defined, but if you add another note not having that field, you’d get the same error as the OP got.

2 Likes

Thank you! I had forgotten the .length

In this case I was actually just going for the number of books read this year, but thanks to your advice I’ll now add a page that includes the list of books in the current year. Thanks!!

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