Special thanks to community contributor @thatgothlibrarian for co-writing this lesson. With his Boolean Logic 101 article, he gracefully provided clear examples to help us wrap our heads around Boolean operators. Do you want to help out writing educational content for the community? Send me a DM!
Does looking at queries cause you anxiety? Does it feel like you need to become a coder to use Logseq fully?
Don’t despair! It all looks scarier than it actually is.
To talk with a database like Logseq, you mostly need to understand how it thinks. In other words: you need to understand the basic logic that Logseq uses to search through your notes.
The type of logic that Logseq follows is called Boolean logic. While you may have never heard of this term, you most likely have applied it before.
Have you ever filtered results on an e-commerce website? For example, to only show results within a specific price range or with a minimum rating? Then you’ve used Boolean logic before.
In this lesson, we dive into the building blocks of Boolean logic:
- True and False
- AND, OR, NOT operators
True or False: the two possible results of Boolean logic
In the world of Boolean logic, things are very black and white. Something is either true, or it’s false; those are the only answers you can get from a Boolean question.
Two possible results, isn’t that very limiting? Remember that computers are dumb, and we must be precise with them. Boolean logic helps us to be precise.
Over the next few days, we’ll learn how Logseq uses Boolean logic. For now, you must remember that Logseq queries only show results that return true as an answer.
Let’s continue with the Boolean operators (called filters in Logseq). We’ll use these to filter out anything we don’t want to see in our search results.
The three basic Boolean operators
There are three basic Boolean operators: AND, OR, and NOT. But despite them being basic, their logic can be somewhat counter-intuitive.
Let’s walk through each step-by-step. To make things less abstract, we’ve assumed you’re a fan of Shakespeare and have lots of notes about his plays (who hasn’t!?). As Shakespeare was kinda obsessed with ghosts (they appear in five of his plays), we’ll use this theme throughout.
An important note: In this lesson, we use something called [pseudocode] for the query examples. We wanted to show you the logic behind Logseq queries without confusing you with the proper way to write them. While actual Logseq queries are close to our pseudocode, please remember that they are written differently. Tomorrow we’ll see the correct way of writing them.
AND
First up, we have AND.
You might think, “Oh hey, AND. That sounds like it increases my results when searching!” But AND actually decreases our search/query results. Let us explain.
Imagine you’re searching through your collection of notes. You want to see everything you have about ‘ghosts’, so you search the keyword [[Ghosts]]
(remember we use [[links]]
as search terms in queries).
Let’s say you get 100 results from that. That’s a lot! You realize you actually only wanted to see results about ghosts in Shakespeare plays. You want to decrease your results, so you search for [[Ghosts]] AND [[Shakespeare]]
. Now you only get 20 results.
AND means that all the results in our example must contain both the keywords [[Ghosts]]
and [[Shakespeare]]
. If we have a Venn diagram of items that contain Ghosts in one circle and items that contain Shakespeare in the other, our search for [[ghosts]] AND [[Shakespeare]]
would give us results that are where those two circles overlap (the orange part in the middle):
OR
On the other hand, what if we wanted results that contain Ghosts or Shakespeare? That’s what OR is for!
OR increases the number of search results.
In a Venn diagram, OR brings us the entirety of both circles and where they overlap. This OR is not exclusionary, meaning results can contain both or either.
You’ll get the 100 results from just searching Ghosts (including the overlaps with Shakespeare), plus any results about Shakespeare and not Ghosts. In our AND search, you wouldn’t have been able to see results about Romeo and Juliet, for example.
NOT
Now we want to see results about Ghosts but not about Shakespeare. So, we search: [[Ghosts]] NOT [[Shakespeare]]
.
Let’s reason about how NOT functions, step-by-step:
- If our original search for Ghosts was 100 results;
- and if our search for
[[Ghosts]] AND [[Shakespeare]]
was only 20 notes; - then, the number of notes about Ghosts but not about Shakespeare is 80.
In a Venn diagram, this query would be only the part of the Ghost circle that didn’t overlap with the Shakespeare circle (the orange part on the left):
Combining Operators
As our notes collection grows, we will need more than just AND, OR, and NOT. We need to combine operators.
Returning to our example, we realize we actually do want to see results about Shakespeare, but we don’t want to see anything about Hamlet or Julius Caesar.
To build our search query, we’ll need to use parentheses. Like in math! This will tell the query how it should combine the operators.
Let’s have a first attempt at the combined query with our current knowledge:
- We want to see all notes about Ghosts:
[[Ghosts]]
- We only want the results that are also about Shakespeare:
[[Ghosts]] AND [[Shakespeare]]
- But we don’t want to see anything about Hamlet:
[[Ghosts]] AND [[Shakespeare]] NOT [[Hamlet]]
- And we don’t want to see anything about Julius Caesar, either. It would make sense for our query to be:
[[Ghosts]] AND [[Shakespeare]] NOT [[Hamlet]] OR [[Julius Caesar]]
. Right?
Nope!
Think about the math problem 1 + 2 x 3.
Is the answer 9? 1 + 2, and then 3 x 3?
No, it’s 7. 2 x 3, and then 6 +1.
An easier way to write this equation is 1 + (2 x 3). The parentheses let us know which part of the equation to do first. In Boolean, parentheses do the same thing.
Let’s revisit what we want to know. We want results about Ghosts and Shakespeare, but we don’t want to see anything about Hamlet or Julius Caesar, which are both plays by Shakespeare.
Let’s start with those two plays: [[Hamlet]] OR [[Julius Caesar]]
.
Julius Caesar, however, is an actual historical figure, and there might be cool ghost stuff about him! So, we need to ensure that the Julius Caesar stuff is only about the Shakespeare play.
For this, our search would be [[Shakespeare]] NOT ([[Hamlet]] OR [[Julius Caesar]])
.
And there’s our first set of parentheses! This is making sure our search is getting us results about Shakespeare, but not Hamlet or Julius Caesar.
Finally, we need to bring ghosts back in since that’s what we really care about: [[Ghosts]] AND ([[Shakespeare]] NOT ([[Hamlet]] OR [[Julius Caesar]]))
.
You’ll notice we put the previous query in its own set of parentheses, and that tells the query that Shakespeare and NOT (Hamlet OR Julius Caesar) are related. This means we can still get stuff about Julius Caesar, the person, but not Julius Caesar, the Shakespeare play. So, whatever results we get here, we can be sure they’re only related to ghosts.
These basics allow us to build practically any workflow we want in Logseq. Tomorrow, we’ll apply this logic to Logseq’s query syntax.
Additional resources
Need to spend some more time to wrap your head around Boolean logic? Check out these additional resources:
- What Boolean Logic Is & How It’s Used In Programming
- Introduction to Boolean Logic
- Boolean Algebra Tutorial
Exercise
Answer the following questions in writing. Don’t just write down the answer; also try to write down the individual steps that Logseq takes to interpret the query.
Post your answers as a comment, and take some time to read the answers of others.
The answer key is below.
- What operator should you use when you want to see results that contain either of two search terms?
- What operator should you use when you only want to see results that contain both of two search terms?
- What operator should you use when you only want to see results that contain one search term but do not contain another search term?
- True or False: given the following query, all blocks containing the link
[[Hamlet]]
will show in the results.
[[Hamlet]] OR [[Shakespeare]]
- True or False: given the following query, all blocks containing the link
[[Ghosts]]
will show in the results.
[[Ghosts]] NOT [[Shakespeare]]
- True or False: given the following query, all blocks containing the link
[[Sharespeare]]
will show in the results.
[[Shakespeare]] AND ([[Hamlet]] NOT [[Ghosts]])
Show answers
- OR
- AND
- NOT
-
True. All blocks and branches that contain
[[Hamlet]]
will appear. However, not all results will contain[[Hamlet]]
as the other half of the query looks at blocks/branches that contain[[Sharespeare]]
, even if they don’t contain[[Hamlet]]
. -
False. Only the blocks that contain
[[Ghosts]]
but not[[Shakespeare]]
will appear. As soon as Logseq encounters[[Shakespeare]]
, the block containing the link and all of its child blocks get filtered out—even if it contains[[Ghosts]]
. -
False. Only the blocks and branches that contain both
[[Shakespeare]]
and[[Hamlet]]
(but not[[Hamlet]]
in combination with[[Ghosts]]
) will appear in the query results.