Query Language🔗
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.
Structure🔗
The overall query is an expression that evaluates to true
or false
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: and
, or
and not
.
Simple expressions check some property of an item. The form is:
<field><operator><value>
For example: tag=invoice
– where tag
is the field, =
the
operator and 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 invoice
.
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 viaAND
(| … )
to combine them viaOR
It is also possible to negate an expression, by prefixing it with a
!
; for example !tag=invoice
.
The Parts🔗
Operators🔗
There are 7 operators:
=
for equals>
for greater-than>=
for greater-equals~=
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<=
for lower-equal!=
for not-equals
Not all operators work with every field.
Fields🔗
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 name
or 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:
name
the item namesource
the source used for uploadingnotes
the item notesid
the item iddate
the item datedue
the due date of the itemcreated
the date when the item was createdcorr.org.id
the id of the correspondent organizationcorr.org.name
the name of the correspondent organizationcorr.pers.name
name of correspondent personcorr.pers.id
id of correspondent personconc.pers.name
name of concerning personconc.pers.id
id of concerning personconc.equip.name
name of equipmentconc.equip.id
id of equipmentfolder.id
id of a folderfolder
name of a folderinbox
whether to return "new" items (boolean)incoming
whether to return incoming items (boolean),true
to show only incoming,false
to show only outgoing.
These fields support all operators, except incoming
and inbox
which expect boolean values and for those some operators don't make
sense.
Fields that map to more than one value:
tag
the tag nametag.id
the tag idcat
name of the tag category
The tag and category fields use two operators: :
and =
.
Other special fields:
attach.id
references the id of an attachmentchecksum
references the sha256 checksum of a filecontent
for fulltext searchf
for referencing custom fields by namef.id
for referencing custom fields by their iddateIn
a shortcut for a range searchdueIn
a shortcut for a range searchcreatedIn
a shortcut for a range searchexist
check if some porperty existsnames
a shortcut to search in several names via:
year
a shortcut for a year rangeconc
a shortcut for concerning person and equipment namescorr
a 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🔗
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🔗
Text values need to be put in quotes ("
) if they contain one of
these characters:
- whitespace
- quotes
"
- backslash
\
- comma
,
- brackets
[]
- parens
()
Any quotes inside a quoted string must be escaped with a backslash.
Examples: scan_123
, a-b-c
, x.y.z
, "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: 1
, 2.15
.
A boolean value can be specfied by yes
or true
and no
or
false
, respectively. Example: inbox:yes
Dates🔗
Dates are always treated as local dates and can be entered in multiple ways.
Date Pattern🔗
They can be in the following form: YYYY-MM-DD
or YYYY/MM/DD
.
The month and day part are optional; if they are missing they are
filled automatically with a 1
. So 2020-01
would be the same as
2020-01-01
.
A special pattern is today
which marks the current day.
Unix Epoch🔗
Dates can be given in milliseconds from unix epoch. Then it must be
prefixed by ms
. The time part is ignored. Examples:
ms1615209591627
.
Calculation🔗
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
semi-colon ;
. Then write a +
or a -
to add or substract and at
last the number of days (suffix d
) or months (suffix m
).
Examples: today;-14d
, 2020-02;+1m
Simple Expressions🔗
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':
name=invoice_22
By using :
, it is possible to look for items that have 'invoice'
somewhere in their name:
name:*invoice*
The asterisk *
can be added at the beginning and/or end of the
value, but not in betwee. Furthermore, the like operator is
case-insensitive, whereas =
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:
corr.pers.name:*marcus*
Comparisons via <
/>
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:
source~=webapp,mailbox
is the same as
(| source=webapp source=mailbox )
The ~=
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
wildcard *
here. If a wildcard is required, you need to write the
longer form.
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 incoming
and inbox
expect a boolean value: one of
true
or false
. The synonyms yes
and no
can also be used to
make it better readable.
This finds all items that have not been confirmed:
inbox:yes
The incoming
can be used to show only incoming or only outgoing
documents:
incoming:yes
For outgoing, you need to say:
incoming:no
Tags🔗
Tags have their own syntax, because they can appear multiple times on
an item. Tags only allow for two operators: =
and :
. Combined with
negation (the !
operator), this is quite flexible.
For tags, =
means that items must have all specified tags (or
more), while :
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
in-operator).
Some examples: Find all invoices that are todo:
tag=invoice,todo
This returns all items that have both tags invoice
and todo
.
Negating this:
!tag=invoice,todo
… results in an expression that returns all items that don't have
both tags. It might return items with tag invoice
and also items
with tag todo
, but no items that have both of them.
Using :
is just analog to =
. This finds all items that are either
waiting
or todo
(or both):
tag:waiting,todo
When negating this:
!tag:waiting,todo
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
instead of tag
.
The field cat
can be used the same way to search for tag categories.
Custom Fields🔗
Custom fields can be used via the following syntax:
f:<field-name><operator><value>
They look almost like a simple expression, only prefixed with a f:
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
in-operator (~=
). 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:
f:usd>10 f:usd<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):
f:asn:*
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 f.id
:
f.id:J2ES1Z4Ni9W-xw1VdFbt3KA-rL725kuyVzh-7La95Yw7Ax2:15.00
Fulltext Search🔗
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':
content:"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)
File Checksums🔗
The 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
disk:
40675c22ab035b8a4ffe760732b65e5f1d452c59b44d3d0a2a08a95d28853497
.
To find all items that have (exactly) this file attached:
checksum:40675c22ab035b8a4ffe760732b65e5f1d452c59b44d3d0a2a08a95d28853497
Exist🔗
The 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
one value.
For example, it could be used to find items that are in any folder:
exist:folder
When negating, it finds all items that are not in a folder:
!exist:folder
Attach-Id🔗
The 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.
attach.id=5YjdnuTAdKJ-V6ofWTYsqKV-mAwB5aXTNWE-FAbeRU58qLb
attach.id=5YjdnuTAdKJ*
Shortcuts🔗
Shortcuts are only a short form of a longer query and are provided for convenience. The following exist:
dateIn
,dueIn
andcreatedIn
year
names
conc
corr
Date Ranges🔗
The first three are all short forms to specify a range search. With
dateIn
and dueIn
have three forms that are translated into a range
search:
dateIn:2020-01;+15d
→date>=2020-01 date<2020-01;+15d
dateIn:2020-01;-15d
→date>=2020-01;-15d date<2020-01
dateIn:2020-01;/15d
→date>=2020-01;-15d date<2020-01;+15d
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.
The 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:
year:2020
→date>=2020-01-01 date<2021-01-01
The last shortcut is names
. It allows to search in many "names" of
related entities at once:
Names🔗
names:tim
→(| name:tim corr.org.name:tim corr.pers.name:tim conc.pers.name:tim conc.equip.name:tim )
The names
field uses the like-operator.
The fields conc
and corr
are analog to names
, only that they
look into correspondent names and concerning names.
conc:marc*
→(| conc.pers.name:marc* conc.equip.name:marc* )
corr:marc*
→(| corr.org.name:marc* corr.pers.name:marc* )
Examples🔗
Find items with at least one tag invoice or todo that are due next:
tag:invoice,todo due>today
Find items with at least both tags invoice and todo:
tag=invoice,todo
Find items with a concerning person of name starting with "Marcus":
conc.pers.name:marcus*
Find items with at least a tag "todo" in year 2020:
tag:todo year:2020
Find items within the last 30 days:
date>today;-30d
Find items with a custom field paid
set to any value:
f:paid:*
Find items that have been paid with more than $100 (using custom
fields paid
as a date and usd
as money):
f:paid:* f:usd>100