Ask
28

How do I write a query that filters notes on a field containing a value, and pulls the tasks from under one specific heading?

I have a few hundred notes with metadata in them, and I want to stop maintaining index pages by hand.

Two things I cannot get working with the query plugin:

First, filtering on a field that holds several values. Matching a field exactly works fine, but I want "notes where the project field includes this project", and comparing with equals returns nothing.

Second, collecting tasks. I can list every unfinished task in a folder, which is too much. What I want is the tasks under a particular heading — each of my meeting notes has an "Actions" section and that is the only part I care about.

What is the right shape for these two queries?

3 answers Share
Report

Answering anonymously — a moderator will review it first.

  • @markdown_mateo · 4h ago

    Worth saying before you build a lot of this: keep the queries simple enough that the note is still readable without the plugin.

    The appeal of plain-text notes is that they are plain text. A vault where the important content is generated by queries is a vault that becomes a directory of empty pages the day the plugin stops being maintained, or the day you want to read your notes on a device that does not run it.

    My rule: queries are for views — dashboards, indexes, task roundups — and never for content. The actual information lives written out in the note. Then a query breaking is an inconvenience rather than a loss.

    It also makes the export question much less frightening, which matters more than it seems until the day you want to leave.

    21
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @query_first_quinn · 4h ago

    Both are solvable and both come down to understanding what the plugin has actually indexed, which is worth ten minutes because it makes every future query obvious.

    First problem: equality versus containment.

    A field written as a list — several values on one key — is indexed as an array, not a string. Comparing an array to a single value with equals is false, always, which is why you get nothing back rather than an error.

    The function you want is the containment one. It works on both arrays and strings, which is what makes it the right default:

    • on an array, it asks whether any element matches
    • on a string, it asks whether the value appears as a substring

    That second behaviour is a trap worth knowing: a substring match means searching for a short project name will also match a longer one containing it. There is a stricter variant that only does exact element matching on arrays — use that when your values are things like admin and admin-review where a substring match would be wrong.

    The general shape is a table query, selecting the columns you want, sourced from a tag or folder, with a where clause using the containment function on your field.

    Second problem: tasks under a heading.

    This is the one people give up on, and it is easy once you know the plugin records where each task was:

    Every indexed task carries a reference to the section it appeared in — effectively a link to that heading in that file. So you filter the task query on that section reference rather than trying to parse the document yourself.

    Use a task query, sourced from wherever your meeting notes live, filtered on the section reference containing your heading name, and add a condition to exclude completed ones. That is the whole query.

    Two details that will bite you here:

    • The heading has to be spelled consistently. "Actions", "Action items" and "Actions:" are three different sections. If your older notes vary, either normalise them or make the filter tolerant.
    • Subtasks are nested, not flat. A task with indented children is indexed as one task with a list of subtasks. If your action items are nested, a plain filter returns only the parents. There is a flatten operation for exactly this — apply it to the subtasks field to get one row per child.

    The general debugging method, which is more valuable than either query: make a scratch note and render the raw metadata of one file. Every serious query plugin has a way to dump what it indexed for a page or a task. Look at that once and you will immediately see whether your field is a string or an array, how the section reference is spelled, and whether your field was parsed at all.

    Most failed queries are a field the plugin never indexed, usually because the metadata is in a format it does not recognise. Checking the index first turns guessing into reading.

    30
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @inline_field_ines · 4h ago

    On the field never being indexed — that is the single most common cause of a query returning nothing, and it is almost always one of these:

    • Front matter that is not valid. One bad line and the whole block is dropped silently, so every field in that note vanishes. Tabs instead of spaces, a colon inside an unquoted value, an unclosed bracket. If one note behaves differently from the rest, check its front matter first.
    • Inline fields with the wrong number of colons. The inline syntax is distinct from the front matter syntax and it is easy to write one when you meant the other.
    • A field inside a code block or a quote, which is deliberately not indexed.
    • The vault not being reindexed after a bulk change made outside the app. A restart or a forced refresh fixes it, and it is worth ruling out before rewriting a query that was correct all along.

    Also: field names are case-sensitive in ways people do not expect, and a trailing space in a name is invisible and fatal.

    27
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report