Notion Formulas 2.0 Deep Dives: Sorting

When Notion shipped Formulas 2.0, it included support for Lists (or Arrays in programming parlance). One of the functions included for working with lists is the sort function. Unlike JavaScript’s sort function, Notion’s sort initially only sorted the list in a very specific way.

				
					[3, 1, 2].sort()  /* => [1, 2, 3] */

				
			

The rules for sorting in Notion are a bit complex, but here’s the general gist (note that this definitely differs from how things are sorted in JavaScript!):

  • Smaller numbers will come before larger ones
  • Earlier dates will come before later ones
  • In general strings are sorted alphabetically, but there are some confusing rules here (see a couple examples below)

"[A-Z]" (uppercase) comes after "[a-z]" (lowercase), in alphabetical order.

This one’s a bit confusing. Here’s an example to showcase:

				
					["B", "A", "b", "a"].sort()  /* => ["a", "A", "b", "B"] */
				
			

If you’re coming from JavaScript, this is going to seem a bit off to you. Here’s the same call in JavaScript. Note the difference:

				
					["B", "A", "b", "a"].sort()  /* => ['A', 'B', 'a', 'b'] */
				
			

In Notion “a’s” come before “b’s”, no matter the case. In JavaScript, uppers come before lowers. You can imagine how this might bite you in the bum if you’re a .js dev and expecting similar in Notion.

"0" (the string representation of the number 0) is treated as a number:

				
					["a", "B", "0", "A", 1, 2].sort() /* => ["0", 1, 2, "a", "A", "B"]
				
			

If you mix property types, you may have some pretty unexpected results with sorting. I think some of these behaviours may be bugs, so heads up! In general you mostly want to only sort lists of the same type (numbers only or letters only).

Since by default the lists were sorted by the above rules, this meant that in order to sort a list in the opposite direction, we had to do something like this:

				
					[3, 1, 2].sort().reverse()  /* => [3, 2, 1] */
				
			

However, as of early December, you can now use an expression passed to sort to modify your sorting. In this case, sort receives what’s referred to as the “current context” which is an expression in which you can utilize two variables:

  1. current — the current item being iterated over in the list
  2. index — the index of the item being iterated over in the list starting from 0 and counting up 

The code inside the () will be run on each item in the list, meaning that, in the following example, current will be first 3, then 1, and finally, 2.

				
					[3, 1, 2].sort(current * -1) /* [3, 2, 1] */

				
			

In the above example, we’re multiplying each item in the list by -1, and that return value is what is used to compare and sort the original list. In effect, this means that the resulting list is sorted in descending order.

Sorting Relations

Originally, when sort was used with a relation property (which also happen to be lists), the relation would be sorted alphabetically using the primary Name field of the page as comparison. But what if you wanted to sort by a property defined on the relation?

Early on, the Notion community figured out a way to work around this. You can see an early example of this I worked on with Thomas Frank in this Sort by Relation property solve. He’s since iterated on this example to a wild conclusion, but here’s the original simple example that sorts the related Videos related to a Channel page by a Views property defined on the Videos database.

				
					/* Start with the related videos */
prop("Videos")

    /* Find all the views for each video */
	.map(current.prop("Views"))

    /* Sort them... */
	.sort()

    /* ...in descending order */
	.reverse()

    /* Look up the Video page by view */
	.map(
	    /* Set a temporary "views" variable to avoid "current" clash */
		lets(
			views, 
			current, 
			prop("Videos").find(current.prop("Views") == views)
		)
	)
				
			
Videos sorted by Views
Videos sorted by Views by using map and find

To make the cool styled visual code shown on the right (and further expressed in Thomas’s tweet), Thomas used the same code as in Sorted Videos and added the replace calls to the views to format the number with commas (Wouldn’t it be nice if Notion added a formatter to formulas?! :))

This allows you to style the number itself, highlighting the video with the most views.

				
					/* Previous code */
prop("Videos")
	.map(current.prop("Views"))
	.sort()
	.reverse()
	.map(
		lets(
			views, 
			current, 
			prop("Videos").find(current.prop("Views") == views)
		)
	)
    /* New code */
	.map(
        /* Use "red" as the color if it's the first item in the list */
		lets(color, index == 0 ? "red" : "",
			/* Add the name of the video and open paranthesis */
			current + " (" +
			/* Use "replace" to format the number with commas */
			current.prop("Views")
				.replace("(\d{1})(\d{3})$","$1,$2")
				.replace("(\d{1})(\d{3},\d{3})$","$1,$2")
				/* Style the number red if first item */
				.style("b", color) + 
			/* Closing paranthesis */
			")"
		)
	)
				
			

Again, here’s how this looks. In the left version, you’ll note that since we just have a list of pages, they are displayed looking similar to a relation property.

Whereas on the right, we see that they have been turned into “text” and represented as a link to the page. In both cases, they still link to the page. Anytime we use a page reference as text like this (for example, concatenating it together with a string), it will automatically be converted into an inline link.

Videos sorted by views with the top performer highlighted
Videos sorted by Views with the top performer highlighted

Of course, these formulas are clunky. But! Now that we can pass an expression to sort and not have to rely on that map/find combo, this is wildly simplified!

Actually sorting the Video relation by Views descending is now as simple as:

				
					prop("Videos").sort(current.prop("Views") * -1)
				
			

Wowza! 🤩

Here we’re using the same method to sort a [3, 1, 2] array by multiplying by -1, except in this case, we’re multiplying the current page’s View property by -1. The original list is organized by this number in turn. Here we can see the same outcome as our previous versions with much less code.

Sorted Videos with the new sort!
Videos sorted by Views descending using the current context.

Pretty sweet! It’s nice to see Notion continuing to iterate to make Formulas 2.0 feel more polished.

Formula Fundamentals

Thanks for reading along! If you want to go deeper on topics like this, you can check out the Formula Fundamentals course (which of course I just updated to document the new sort functionality).

We also just added a new Changelog to the course where we’ll be posting updates to the course as well as notes about what’s changed about Formulas over time in general.

The Formula Fundamentals Changelog
The Formula Fundamentals Changelog

Share This Post

LinkedIn
Twitter
Email

Get 🔥 Notion tips in your inbox

When you sign up, you’ll get tips, perspectives, and opinions on how you can better use Notion. Plus you’ll get a steady drip of Notion updates, videos, interviews, and resources from the Notion Mastery team.

Master your life and business workflows with Notion.