Can't Sort Dataviewjs Query by Date

What I’m trying to do

I’m trying to list some files in the Changelog folder and sort them by date. The solution is probably really simple, but I haven’t found it yet.

Things I have tried

So, this is my current query:

let pages = dv.pages()
.where(p => p.file.path.includes("Changelog"))
.sort(k => k.date); // <== This is where I try to sort.

// I'm gonna use this variable to format listed note info
let events = ``;

for (let group of pages.groupBy(b => b.file.link))  {

// with each file, add the date, link, and body fields as a '+' list
	events += `
+ ${String(group.rows.date).replaceAll("[", "").replaceAll("]", "")}
+ ${group.key}
+ ${String(group.rows.body).replaceAll("[", "").replaceAll("]", "")}`;
	}

// render as a timeline codeblock with the formatted '+' list
dv.paragraph(`~~~timeline
${events}
~~~`);

It renders like this. The real titles are not shown in the picture, but in reality, it is sorting by file name alphabetically.

I’ve also tried these variants of sort:

.sort(k => Number(k.date));

.sort(k => Date(k.date));

.sort(k => Date(k.date)).getFullYear();

.sort(k => k.date.getFullYear();

And I’ve tried applying the sort function at groupBy. I’m probably misunderstanding sort() or using it the wrong way.

Also, the Date field is just a year, which is why I tried .getFullYear.

What do you get if you console.log(pages) before the for loop? Does it list the pages in the correct order?

You’re replacing the square brackets of both the date and body, are any of these actually links since you do that replacement? Could you show case how one of your definitions for date looks like? Is it placed in the frontmatter, or the body, or a list item?

Using console.log does list them in correct order. Interesting!

For date and body, none of them are links, but they are all wrapped in brackets (I guess because it assumes they are in an array). So I got rid of the brackets just to make them look better.

Date is in the frontmatter and is a single year.

---
date: 2019
---
1 Like

Perhaps the date needs a full ISO-compliant date (YYYY-MM / YYYY-MM-DD) with just the year extracted for the query?

https://blacksmithgu.github.io/obsidian-dataview/annotation/types-of-metadata/#date

1 Like

I’ve seen this in a few cases, that the .groupBy needs (or just do) reorder the list, so the question then becomes, what does that .groupBy do? And can we circumvent this somehow?

Like, does the following do the trick, or does this introduce other errors?

```dataviewjs

const myFolder = dv.current().file.folder
const REMOVE_BRACKETS = /[\][]+/g
let pages = dv.pages()
  .where(p => p.file.path.includes("ChangeLog")
  .groupBy(p => [p.date, p.file.link])
  .sort(p => p.key[0], "asc") // Here the sort is _after_ the grouping
  .map(p => `
+ ${ String(p.rows.date).replace(REMOVE_BRACKETS, "") }
+ ${ p.key[1] }
+ ${ String(p.rows.body).replace(REMOVE_BRACKETS, "") }
`)

console.log(pages)

dv.paragraph(`~~~timeline
${ pages.join("\n") }
~~~`)
```

The trick used here is to add the year into the group by construct, so that now it’s not only the file which is used for grouping, but also the year.

This will also potentially address a case related to what do you expect to happen if a file have multiple dates in a range overlapping with another file, or what is the initial intention of doing the group by on the file link? What does it group then?

At least in my simple test cases, this allows for the “asc” to be switched around to “desc”, and the list reverses.

1 Like

Wow, that worked! Thank you so much, @holroy.

So, in your modified version, the pages are grouped, then sorted, and the array itself is changed with .map() and merged with .join() for the final output. That makes sense. I never quite understood .map() before, so I learned a lot from this!

1 Like

I’m still kind of uncertain as to why you’re grouping the result, and whether you can’t just have it sorted by year (and potentially file.name in addition), and skip the grouped by part.

But then again, if you’re happy, then I’m happy! :smiley:

I just used groupBy because I saw someone else use groupBy to list some files. And it just worked, so I didn’t really question it. I don’t know a lot of javascript, so I’ve mostly been copying others :laughing: .

I did go back to the Timeline query you helped me with to get rid of groupBy and replace the group.rows and group.key instances with the actual variable names just to see if it would work. And it did, hooray!

I guess earlier I just assumed I had to group the pages for the metadata to show up in the right order, but now I can see that it definitely does not work like that.

1 Like

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