mu/man/mu-query.7.org

340 lines
10 KiB
Org Mode
Raw Normal View History

#+TITLE: MU QUERY
#+MAN_CLASS_OPTIONS: :section-id "@SECTION_ID@" :date "@MAN_DATE@"
* NAME
mu query language -- a language for finding messages in *mu* databases.
* DESCRIPTION
The mu query language is a language used by *mu find* and *mu4e* to find messages in
*mu*'s Xapian databases. The language is quite similar to Xapian's default
query-parser, but is an independent implementation that is customized for the
mu/mu4e use-case.
In this article, we give a structured but informal overview of the query
language and provide examples.
As a companion to this, we recommend the *mu fields* and *mu flags* commands to get
an up-to-date list of the available fields and flags.
*NOTE:* if you use queries on the command-line (say, for *mu find*), you need to
quote any characters that would otherwise be interpreted by the shell, such as
*""*, *(* and *)* and whitespace.
* TERMS
The basic building blocks of a query are *terms*; these are just normal words like
'banana' or 'hello', or words prefixed with a field-name which make them apply
to just that field. See *mu find* for all the available fields.
Some example queries:
#+begin_example
vacation
subject:capybara
maildir:/inbox
#+end_example
Terms without an explicit field-prefix, (like 'vacation' above) are interpreted
like:
#+begin_example
to:vacation or subject:vacation or body:vacation or ...
#+end_example
The language is case-insensitive for terms and attempts to 'flatten' any
diacritics, so =angtrom= matches =Ångström=.
If terms contain whitespace, they need to be quoted:
#+begin_example
subject:"hi there"
#+end_example
This is a so-called =phrase query=, which means that we match against subjects
that contain the literal phrase "hi there".
Remember that you need to escape those quotes when using this from the
command-line:
#+begin_example
mu find subject:\\"hi there\\"
#+end_example
* LOGICAL OPERATORS
We can combine terms with logical operators -- binary ones: *and*, *or*, *xor* and the
unary *not*, with the conventional rules for precedence and association, and are
case-insensitive.
You can also group things with *(* and *)*, so you can do things like:
#+begin_example
(subject:beethoven or subject:bach) and not body:elvis
#+end_example
If you do not explicitly specify an operator between terms, *and* is implied, so
the queries
#+begin_example
subject:chip subject:dale
#+end_example
#+begin_example
subject:chip AND subject:dale
#+end_example
are equivalent. For readability, we recommend the second version.
Note that a =pure not= - e.g. searching for *not apples* is quite a 'heavy' query.
* REGULAR EXPRESSIONS AND WILDCARDS
The language supports matching basic PCRE regular expressions, see *pcre(3)*.
Regular expressions are enclosed in *//*. Some examples:
#+begin_example
subject:/h.llo/ # match hallo, hello, ...
subject:/
#+end_example
Note the difference between 'maildir:/foo' and 'maildir:/foo/'; the former
matches messages in the '/foo' maildir, while the latter matches all messages in
all maildirs that match 'foo', such as '/foo', '/bar/cuux/foo', '/fooishbar'
etc.
Wildcards are an older mechanism for matching where a term with a rightmost ***
(and =only= in that position) matches any term that starts with the part before
the ***; they are supported for backward compatibility and *mu* translates them to
regular expressions internally:
#+begin_example
foo*
#+end_example
is equivalent to
#+begin_example
/foo.*/
#+end_example
As a note of caution, certain wild-cards and regular expression can take quite a
bit longer than 'normal' queries.
* FIELDS
We already saw a number of search fields, such as *subject:* and *body:*. For the
2023-07-06 06:39:55 +02:00
full table with all details, including single-char shortcuts, try the command:
~mu info fields~.
|------------+-----------+--------------------------------|
| field-name | alias | description |
| bcc | | Blind carbon-copy recipient |
| body | | Message plain-text body |
| cc | | Carbon-copy recipient |
| changed | | Last change time |
| date | | Message date |
| embed | | Embedded text |
| file | | Attachment file name |
| flags | flag | Message properties |
| from | | Message sender |
| language | lang | ISO 639-1 language code (*) |
| maildir | | Maildir path for message |
| list | | Mailing list (List-Id:) |
| message-id | msgid | Message-Id |
| mime | mime-type | Attachment MIME-type |
| path | | File system path to message |
| priority | prio | Priority |
| references | | References to related messages |
| size | | Message size in bytes |
| subject | | Message subject |
| tags | tag | Message tags |
| thread | | Thread a message belongs to |
| to | | Message recipient |
|------------+-----------+--------------------------------|
(*) The language code for the text-body if found. This works only
if ~mu~ was built with CLD2 support.
There are also the special fields *contact:*, which matches all contact-fields
(=from=, =to=, =cc= and =bcc=), and *recip*, which matches all recipient-fields (=to=, =cc=
and =bcc=).
Hence, for instance,
#+begin_example
contact:fnorb@example.com
#+end_example
is equivalent to
#+begin_example
(from:fnorb@example.com or to:fnorb@example.com or
cc:from:fnorb@example.com or bcc:fnorb@example.com)
#+end_example
* DATE RANGES
The *date:* field takes a date-range, expressed as the lower and upper bound,
separated by *..*. Either lower or upper (but not both) can be omitted to create
an open range.
Dates are expressed in local time and using ISO-8601 format (YYYY-MM-DD
HH:MM:SS); you can leave out the right part, and *mu* adds the rest, depending on
whether this is the beginning or end of the range (e.g., as a lower bound,
'2015' would be interpreted as the start of that year; as an upper bound as the
end of the year).
You can use '/' , '.', '-' and 'T' to make dates more human readable.
Some examples:
#+begin_example
date:20170505..20170602
date:2017-05-05..2017-06-02
date:..2017-10-01T12:00
date:2015-06-01..
date:2016..2016
#+end_example
You can also use the special 'dates' *now* and *today*:
#+begin_example
date:20170505..now
date:today..
#+end_example
Finally, you can use relative 'ago' times which express some time before now and
consist of a number followed by a unit, with units *s* for seconds, *M* for minutes,
*h* for hours, *d* for days, *w* for week, *m* for months and *y* for years. Some
examples:
#+begin_example
date:3m..
date:2017.01.01..5w
#+end_example
* SIZE RANGES
The *size* or *z* field allows you to match =size ranges= -- that is, match messages
that have a byte-size within a certain range. Units (b (for bytes), K (for 1000
bytes) and M (for 1000 * 1000 bytes) are supported). Some examples:
#+begin_example
size:10k..2m
size:10m..
#+end_example
* FLAG FIELD
The *flag/g* field allows you to match message flags. The following fields are
available:
#+begin_example
a,attach Message with attachment
d,draft Draft Message
f,flagged Flagged
l,list Mailing-list message
n,new New message (in new/ Maildir)
p,passed Passed ('Handled')
r,replied Replied
s,seen Seen
t,trashed Marked for deletion
u,unread new OR NOT seen
x,encrypted Encrypted message
z,signed Signed message
#+end_example
Some examples:
#+begin_example
flag:attach
flag:replied
g:x
#+end_example
Encrypted messages may be signed as well, but this is only visible after
decrypting and thus invisible to *mu*.
* PRIORITY FIELD
The message priority field (*prio:*) has three possible values: *low*, *normal* or
*high*. For instance, to match high-priority messages:
#+begin_example
prio:high
#+end_example
* MAILDIR
The Maildir field describes the directory path starting *after* the Maildir-base
path, and before the =/cur/= or =/new/= part. So for example, if there's a message
with the file name =~/Maildir/lists/running/cur/1234.213:2,=, you could find it
(and all the other messages in the same maildir) with:
#+begin_example
maildir:/lists/running
#+end_example
Note the starting '/'. If you want to match mails in the 'root' maildir, you can
do with a single '/':
#+begin_example
maildir:/
#+end_example
If you have maildirs (or any fields) that include spaces, you need to quote
them, ie.
#+begin_example
maildir:"/Sent Items"
#+end_example
Note that from the command-line, such queries must be quoted:
#+begin_example
mu find 'maildir:"/Sent Items"'
#+end_example
* MORE EXAMPLES
Here are some simple examples of *mu* queries; you can make many more complicated
queries using various logical operators, parentheses and so on, but in the
author's experience, it's usually faster to find a message with a simple query
just searching for some words.
Find all messages with both 'bee' and 'bird' (in any field)
#+begin_example
bee AND bird
#+end_example
Find all messages with either Frodo or Sam:
#+begin_example
Frodo OR Sam
#+end_example
Find all messages with the 'wombat' as subject, and 'capybara' anywhere:
#+begin_example
subject:wombat and capybara
#+end_example
Find all messages in the 'Archive' folder from Fred:
#+begin_example
from:fred and maildir:/Archive
#+end_example
Find all unread messages with attachments:
#+begin_example
flag:attach and flag:unread
#+end_example
Find all messages with PDF-attachments:
#+begin_example
mime:application/pdf
#+end_example
Find all messages with attached images:
#+begin_example
mime:image/*
#+end_example
Find all messages written in Dutch or German with the word 'hallo':
#+begin_example
hallo and (lang:nl or lang:de)
#+end_example
* CAVEATS
With current Xapian versions, the apostroph character is considered part of a
word. Thus, you cannot find =D'Artagnan= by searching for =Artagnan=. So, include
2023-07-06 06:39:55 +02:00
the apostrophe in search or use a regexp search.
Matching on spaces has changed compared to the old query-parser; this applies
e.g. to Maildirs that have spaces in their name, such as =Sent Items=. See *MAILDIR*
above.
#+include: "prefooter.inc" :minlevel 1
* SEE ALSO
2023-07-06 06:39:55 +02:00
*mu-find(1)*, *mu-info(1), *pcre(3)*