Querying for todos where tag1 AND tag2 are present (edn)

Disclaimer… I am relatively new to logseq and edn, hopfully this is an easy thing to do, but despite several hours of googling and trial and error, i am still unable to get a query that works…
What i am trying to do is set up my config.edn to have a default journal query for all TODOs that include tag1 AND tag2.
The idea being i have short easy to complete tasks tagged with tag1, tasks related to my business tagged with tag2, and tasks related to my personal life tagged with tag3.
I want 2 sections on my journal page… “Quick Wins - Personal” and “Quick Wins - Business”.
The first should be all TODOs that include tag1 and tag2, and the second should be all TODOs that include tag1 and tag3.
Any help here would be greatly appreciated!


  • If in the query that task-block is represented by ?h, then to require that it contains both tag1 and tag2, could use the following:
    [?ref1 :block/name "tag1"]
    [?ref2 :block/name "tag2"]
    [?h :block/refs ?ref1]
    [?h :block/refs ?ref2]
  • If you still have issues, make sure to share your effort (query + example tasks), so as we have something concrete to help you with.
1 Like

Ah ha! That worked perfectly! Thank you!
Just for my own understanding (as im still trying to wrap my head around edn), [?ref1 :block/name "tag1"] filters ?h for blocks that have name “tag1”, [?ref2 :block/name "tag2"] filters ?h for blocks that have name “tag2”, and then [?h :block/refs ?ref1] and [?h :block/refs ?ref2] essentially make an intersection between both sets?

Im curious too… If i wanted to make a 3rd section marked as Quick Wins - Uncategorized such that it shows all tasks tagged with tag1 but not tag2 or tag3… How might i go about that…?

  • This is datalog.
    • Make sure that you read it at least once.
  • Same-level clauses often (but not always) participate in an implicit AND.
    • You may call that an intersection.
      • Calling it filtering is preferable.
  • To exclude a tag, put its inclusion inside a not-clause:
      [?ref3 :block/name "tag3"]
      [?h :block/refs ?ref3]
    • This not is within an implicit top-level AND.
    • The two lines inside not are also within a local implicit AND.
  • For multiple conditions, you may combine the clauses in more than one ways, e.g.:
    • (and (not a) (not b) (not c))
      • this is better fitting in your particular case
    • (not (or a b c))
      • this is for homework
1 Like

To further explain what is going on it should be read as such:
Define variable ?ref1 as the entity id with an attribute that has a name and value of :block/name and tag1.
Define variable ?h as the entity id with an attribute that has a name and value of :block/refs and ?ref1 (which is the entity id that we defined earlier).
AND the same entity id ?h also has in that same attribute of :block/refs the value of ?ref2. (:block/refs actually is a kind of list)

Also this is datalog and not edn. edn is the format of the file this datalog appears in.
Datalog queries can also appear in Logseq pages, which are in the .md format.

1 Like

Thank you for the guidance!
I wasn’t actually able to get your code snippet to work… but i was able to tweak it and get this to work

[?ref1 :block/name "tag1"]
[?ref2 :block/name "tag2"]
[?ref3 :block/name "tag3"]
[?b :block/refs ?ref1]
(not [?b :block/refs ?ref2])
(not [?b :block/refs ?ref3])

Maybe i did something wrong, but i wasn’t able to get the grouping to work as in your example.
Regardless, i appreciate the feedback!