How to query in Roam

There are two ways to query in Roam, a simple way using the {{query: }} function, and a more advanced way using a scripting language called DataScript to query the guts of the underlying Clojure database.

Simple querying with {{query: }}

The format is:

{{query: what you're looking for }}

You can type a query into any block on any page. “Query” searches for specific blocks (not pages!) across your whole database that match your search criteria.

There are 4 logical words you can use to increase the specificity of what you’re looking for. These words are called operators and are AND, OR, NOT, and BETWEEN.

{and: [[tagA]] [[tagB]]}Find blocks containing both tagA and tagB
{or: [[tagA]] [[tagB]]}Find blocks containing tagA or tagB (or both)
{not: [[tagA]] [[tagB]]}Find blocks that have neither tagA nor tagB
{between: [[January 1st, 2020]] [[today]]}Find blocks that have dates between 1 Jan 2020 and the day that the query is run (ie it keeps “up to date”).
Note: You can only use [[today]] on the DAILY NOTES page.

Let’s try this. If you want to find all blocks in your whole database linking to the page Singapore you would do this:

{{query: {and:[[Singapore]]} }}

Let’s find blocks that link to Singapore and London. Just put the two links next to each other inside the and braces:

{{query: {and:[[Singapore]] [[London]]} }}

Now let’s find blocks that link to Singapore but not London. We’re really querying for links to Singapore AND (NOT London), so your not clause goes inside the and clause’s curly braces.

{{query: {and:[[Singapore]] {not:[[London]]} } }}

Let’s find blocks that have a link to either Singapore, or London (or both). This will return a larger number of results than the AND query.

{{query: {or:[[Singapore]] [[London]] } }}

Finally, people use Roam for to do lists, and it’s common to want to search for blocks tagged [[TODO]] between some dates. You can use between.

{{query: {and: [[TODO]] {between: [[January 1st, 2020]] [[May 1st, 2020]]} } }}

Often you care about things happening before or after today. You can use today, but only on the DAILY NOTES page.

{{query: {and: [[TODO]] {between: [[January 1st, 2020]] [[Today]]} } }}

Gotchyas

There are some things to be aware about.

Self-reference

Queries search your whole database, including the query block itself. This means that often your query will return itself in its results, which can be annoying. So to avoid this, it’s common to turn the query function into a link to a page by enclosing it in square brackets (ie [[query]]), then exclude that page by adding {not: [[query]]} like so:

Before: {{query: {and:[[Singapore]] [[London]]} }}
After:  {{[[query]]: {and:[[Singapore]] [[London]] {not:[[query]]} } }}

Page names

Earlier we discussed that queries search at the block level. Blocks contain more data than meets the eye. As well as the text written in the block, you can think of blocks also containing a ‘virtual’ tag to their page’s name.

So for example on the Singapore page:

Singapore

  • National dishes are [[chilli crab]] and [[laksa]].
  • [[Orchard Road]] is a popular shopping district.

For the purposes of queries, you can think of each block with a virtual [[Singapore]] tag on them:

  • [[Singapore]] National dishes are [[chilli crab]] and [[laksa]].
  • [[Singapore]] [[Orchard Road]] is a popular shopping district.

This means that if you want to return blocks from a specific page, you can include the page’s name in the and clause, (even though the page name isn’t visible in the blocks):

{{query: {and:[[chilli crab]] [[Singapore]]} }}

The above will return:

  • all blocks on the Singapore page containing a reference to [[chilli crab]], and
  • all blocks on the chilli crab page containing a reference to [[Singapore]], and
  • all other blocks in your database that contain references to both [[chilli crab]] and [[Singapore]].

There is still some way to go with the {{query}} function. For example it is not possible to create a query that would return results only from a specific page or set of pages.

For more advance stuff, we have to search using Datascript, a more powerful but less intuitive way of interrogating your database.

Advanced querying with DataScript

[[coming soon!]]

%d bloggers like this: