Docspell uses a query language to provide a powerful way to search for your documents. It currently needs to be enabled explicitely in your user settings to be used on the search page.
This changes the search bar on the items list page to expect a query as described below.
The search menu works as before, the query coming from the search menu is combined with a query from the search bar.
For taking a quick look, head over to the examples.
The overall query is an expression that evaluates to
when applied to an item and so selects whether to include it in the
results or not. It consists of smaller expressions that can be
combined via the common ways:
Simple expressions check some property of an item. The form is:
tag=invoice – where
tag is the field,
invoice the value. It would evaluate to
true if the
item has a tag with name
invoice and to
false if the item doesn't
have a tag with name
Multiple expressions are separated by whitespace and are combined via
AND by default. To explicitely combine them, wrap a list of
expressions into one of these:
(& … )to combine them via
(| … )to combine them via
It is also possible to negate an expression, by prefixing it with a
!; for example
There are 7 operators:
~=for "in" (a shorter way to say "a or b or c or d")
:for "like", this is used in a context-sensitive way
<for lower than
Not all operators work with every field.
Fields are used to identify a property of an item. They also define
what operators are allowed. There are fields where an item can have at
most one value (like
notes) and there are fields where an
item can have multiple values (like
tag). At last there are special
fields that are either implemented directly using custom sql or that
are only shortcuts to a longer form.
Here is the list of all available fields.
These fields map to at most one value:
namethe item name
sourcethe source used for uploading
notesthe item notes
idthe item id
datethe item date
duethe due date of the item
createdthe date when the item was created
corr.org.idthe id of the correspondent organization
corr.org.namethe name of the correspondent organization
corr.pers.namename of correspondent person
corr.pers.idid of correspondent person
conc.pers.namename of concerning person
conc.pers.idid of concerning person
conc.equip.namename of equipment
conc.equip.idid of equipment
folder.idid of a folder
foldername of a folder
inboxwhether to return "new" items (boolean)
incomingwhether to return incoming items (boolean),
trueto show only incoming,
falseto show only outgoing.
These fields support all operators, except
which expect boolean values and for those some operators don't make
Fields that map to more than one value:
tagthe tag name
tag.idthe tag id
catname of the tag category
The tag and category fields use two operators:
Other special fields:
attach.idreferences the id of an attachment
checksumreferences the sha256 checksum of a file
contentfor fulltext search
ffor referencing custom fields by name
f.idfor referencing custom fields by their id
dateIna shortcut for a range search
dueIna shortcut for a range search
createdIna shortcut for a range search
existcheck if some porperty exists
namesa shortcut to search in several names via
yeara shortcut for a year range
conca shortcut for concerning person and equipment names
corra shortcut for correspondent org and person names
These fields are often using the
: operator to simply separate field
and value. They are often backed by a custom implementation, or they
are shortcuts for a longer query.
Values are the data you want to search for. There are different kinds
of that, too: there are text values, numbers, boolean and dates. When
multiple values are allowed, they must be separated by comma
Text values need to be put in quotes (
") if they contain one of
Any quotes inside a quoted string must be escaped with a backslash.
"scan from today",
"a \"strange\" name.pdf"
Numeric and Boolean Values🔗
Numeric values can be entered literally; an optional fraction part is
separetd by a dot. Examples:
A boolean value can be specfied by
false, respectively. Example:
Dates are always treated as local dates and can be entered in multiple ways.
They can be in the following form:
The month and day part are optional; if they are missing they are
filled automatically with a
2020-01 would be the same as
A special pattern is
today which marks the current day.
Dates can be given in milliseconds from unix epoch. Then it must be
ms. The time part is ignored. Examples:
Dates can be defined by providing a base date via the forms above and
a period to add or substract. This is especially useful with the
today pattern. The period must be separated from the date by a
;. Then write a
+ or a
- to add or substract and at
last the number of days (suffix
d) or months (suffix
Simple expressions are made up of a field with at most one value, an operator and one or more values. These fields support all operators, except for boolean fields.
The like operator
: can be used with all values, but makes only
sense for text values. It allows to do a substring search for a field.
For example, this looks for an item with a name of exactly 'invoice_22':
:, it is possible to look for items that have 'invoice'
somewhere in their name:
* can be added at the beginning and/or end of the
value, but not in betwee. Furthermore, the like operator is
= is not. This applies to all fields with
a text value.
This is another example looking for a correspondent person of with 'marcus' in the name:
> are done alphanumerically for text based
values and numerically for numeric values. For booleans these
operators don't make sense and therefore don't work there.
All these fields (except boolean fields) allow to use the in-operator,
~=. This is a more efficient form to specify a list of alternative
values for the same field. It is logically the same as combining
multiple expressions with
OR. For example:
is the same as
(| source=webapp source=mailbox )
~= version is nicer to read, safes some key strokes and also
runs more efficient when the list grows. It is not possible to use a
* here. If a wildcard is required, you need to write the
If one value contains whitespace or other characters that require quoting, each value must be quoted, not the whole list. So this is correct:
source~="web app","mail box"
This is not correct:
source~="web app,mail box" – it would be treated
as one single value and is then essentially the same as using
The two fields
inbox expect a boolean value: one of
false. The synonyms
no can also be used to
make it better readable.
This finds all items that have not been confirmed:
incoming can be used to show only incoming or only outgoing
For outgoing, you need to say:
Tags have their own syntax, because they can appear multiple times on
an item. Tags only allow for two operators:
:. Combined with
! operator), this is quite flexible.
= means that items must have all specified tags (or
: means that items must have at least one of the
specified tags. Tags can be identified by their name or id and are
given as a comma separated list (just like when using the
Some examples: Find all invoices that are todo:
This returns all items that have both tags
… results in an expression that returns all items that don't have
both tags. It might return items with tag
invoice and also items
todo, but no items that have both of them.
: is just analog to
=. This finds all items that are either
todo (or both):
When negating this:
it finds all items that have none of the tags.
Tag names are always compared case-insensitive. Tags can also be
selected using their id, then the field name
tag.id must be used
cat can be used the same way to search for tag categories.
Custom fields can be used via the following syntax:
They look almost like a simple expression, only prefixed with a
to indicate that the following is the name of a custom field.
The type of a custom field is honored. So if you have a money or
numeric type, comparsions are done numerically. Otherwise a
alphnumeric comparison is performed. Custom fields do not support the
~=). Date fields are an exception: they are always
compared alphanumerically and thus the
today special value doesn't
work with them.
For example: assuming there is a custom field of type money and name usd, the following selects all items with an amount between 10 and 150:
The like-operator can be used, too. For example, to find all items
that have a custom field
asn (often used for a serial number printed
on the document):
If the like operator is used on numeric fields, it falls back to text-comparison.
Instead of using the name, the field-id can be used to select a field.
Then the prefix is
The special field
content allows to add a fulltext search. Using
this is currently restricted: it must occur in the root (AND) query
and cannot be nested in other complex expressions.
The form is:
content:<your search query>
The search query is interpreted by the fulltext index (currently it is SOLR). This is usually very powerful and in many cases this value must be quoted.
For example, do a fulltext search for 'red needle':
It can be combined in an AND expression:
content:"red needle" tag:todo
But it can't be combined via OR. This is not possible:
tag:todo (| content:"red needle" tag:waiting)
checksum field can be used to look for items that have a certain
file attached. It expects a SHA256 string.
For example, this is the sha256 checksum of some file on the hard
To find all items that have (exactly) this file attached:
exist field can be used with another field, to check whether an
item has some value for it. It only works for fields that have at most
For example, it could be used to find items that are in any folder:
When negating, it finds all items that are not in a folder:
attach.id field is a special field to find items by providing
the id of an attachment. This can be helpful in certain situations
when you only have the id or part of that of an attachment. It uses
equality if no wildcard is present. A wildcard
* can be used at
beginning or end if only a part of the id is known.
Shortcuts are only a short form of a longer query and are provided for convenience. The following exist:
The first three are all short forms to specify a range search. With
dueIn have three forms that are translated into a range
The syntax is the same as defining a date by adding a period to some
base date. These two dates are used to expand the form into a range
search. There is an additional
/ character to allow to subtract and
add the period.
year is almost the same thing, only a lot shorter to write. It
expands into a range search (only for the item date!) that selects all
items with a date in the specified year:
The last shortcut is
names. It allows to search in many "names" of
related entities at once:
(| name:tim corr.org.name:tim corr.pers.name:tim conc.pers.name:tim conc.equip.name:tim )
names field uses the like-operator.
corr are analog to
names, only that they
look into correspondent names and concerning names.
(| conc.pers.name:marc* conc.equip.name:marc* )
(| corr.org.name:marc* corr.pers.name:marc* )
Find items with at least one tag invoice or todo that are due next:
Find items with at least both tags invoice and todo:
Find items with a concerning person of name starting with "Marcus":
Find items with at least a tag "todo" in year 2020:
Find items within the last 30 days:
Find items with a custom field
paid set to any value:
Find items that have been paid with more than $100 (using custom
paid as a date and
usd as money):