foo|<text:"foo">
foo (bar)|<text:"foo" context:"bar">
foo "bar"|(<text:"foo "> AND <exact_text:"bar">)
"foo" bar|(<exact_text:"foo"> AND <text:" bar">)
# foo ("bar baz")|<text:"foo" context:"bar baz">
foo bar|<text:"foo bar">
foo bar (baz qux)|<text:"foo bar" context:"baz qux">
"foo bar"|<exact_text:"foo bar">
# "foo bar" (baz)|<exact_text:"foo bar" context:"baz qux">
[foo]|<term:"foo">
[foo (bar)]|<term:"foo" context:"bar">
[foo bar (baz qux)]|<term:"foo bar" context:"baz qux">

# Raw string
r"foo"|<raw:"foo">
r"foo bar"|<raw:"foo bar">
r"\"foo\""|<raw:""foo"">
r"\o/"|<raw:"\o/">
r"\\o/"|<raw:"\o/">
r"foo \n bar"|<raw:"foo \n bar">
r"foo\\nbar"|<raw:"foo\nbar">

# Parenthesis grouping
(foo)|<text:"foo">
(foo bar)|<text:"foo bar">
(foo OR bar) AND baz|((<text:"foo"> OR <text:"bar">) AND <text:"baz">)

# Boolean operators
foo AND bar|(<text:"foo"> AND <text:"bar">)
foo AND bar AND baz|((<text:"foo"> AND <text:"bar">) AND <text:"baz">)
foo AND bar OR baz|((<text:"foo"> AND <text:"bar">) OR <text:"baz">)
foo AND bar EXCEPT baz|((<text:"foo"> AND <text:"bar">) EXCEPT <text:"baz">)
foo AND (bar AND baz)|(<text:"foo"> AND (<text:"bar"> AND <text:"baz">))
foo AND (bar OR baz)|(<text:"foo"> AND (<text:"bar"> OR <text:"baz">))
foo AND (bar EXCEPT baz)|(<text:"foo"> AND (<text:"bar"> EXCEPT <text:"baz">))
foo OR bar|(<text:"foo"> OR <text:"bar">)
foo OR bar AND baz|(<text:"foo"> OR (<text:"bar"> AND <text:"baz">))
foo OR bar OR baz|((<text:"foo"> OR <text:"bar">) OR <text:"baz">)
foo OR bar EXCEPT baz|((<text:"foo"> OR <text:"bar">) EXCEPT <text:"baz">)
foo OR (bar AND baz)|(<text:"foo"> OR (<text:"bar"> AND <text:"baz">))
foo OR (bar OR baz)|(<text:"foo"> OR (<text:"bar"> OR <text:"baz">))
foo OR (bar EXCEPT baz)|(<text:"foo"> OR (<text:"bar"> EXCEPT <text:"baz">))
foo EXCEPT bar|(<text:"foo"> EXCEPT <text:"bar">)
foo EXCEPT bar AND baz|(<text:"foo"> EXCEPT (<text:"bar"> AND <text:"baz">))
foo EXCEPT bar OR baz|(<text:"foo"> EXCEPT (<text:"bar"> OR <text:"baz">))
foo EXCEPT bar EXCEPT baz|((<text:"foo"> EXCEPT <text:"bar">) EXCEPT <text:"baz">)
foo EXCEPT (bar AND baz)|(<text:"foo"> EXCEPT (<text:"bar"> AND <text:"baz">))
foo EXCEPT (bar OR baz)|(<text:"foo"> EXCEPT (<text:"bar"> OR <text:"baz">))
foo EXCEPT (bar EXCEPT baz)|(<text:"foo"> EXCEPT (<text:"bar"> EXCEPT <text:"baz">))

# Comparison operators
foo < 42|<range:field.foo lt="42">
foo ≤ 42|<range:field.foo lte="42">
foo > 42|<range:field.foo gt="42">
foo ≥ 42|<range:field.foo gte="42">
foo = 2015/01/01|(<field.foo> == <value:"2015/01/01">)
foo < 2015/01/01|<range:field.foo lt="2015/01/01">
foo ≤ 2015/01/01|<range:field.foo lte="2015/01/01">
foo > 2015/01/01|<range:field.foo gt="2015/01/01">
foo ≥ 2015/01/01|<range:field.foo gte="2015/01/01">
foo < "2015/01/01"|<range:field.foo lt="2015/01/01">
foo ≤ "2015/01/01"|<range:field.foo lte="2015/01/01">
foo > "2015/01/01"|<range:field.foo gt="2015/01/01">
foo ≥ "2015/01/01"|<range:field.foo gte="2015/01/01">
foo = 42|(<field.foo> == <value:"42">)
foo = bar|(<field.foo> == <value:"bar">)
foo = "bar"|(<field.foo> == <value:"bar">)

# Field narrowing
foo:bar|(<field:foo> MATCHES <text:"bar">)
foo:[bar]|(<field:foo> MATCHES <term:"bar">)
foo:[bar (baz)]|(<field:foo> MATCHES <term:"bar" context:"baz">)
foo:bar baz|((<field:foo> MATCHES <text:"bar">) AND <text:"baz">)
foo bar:baz|(<text:"foo"> AND (<field:bar> MATCHES <text:"baz">))

# Regular field with name colliding with a native key
field.collection:foo|(<field:collection> MATCHES <text:"foo">)
field.database:foo|(<field:database> MATCHES <text:"foo">)
field.type:foo|(<field:type> MATCHES <text:"foo">)
field.id:foo|(<field:id> MATCHES <text:"foo">)

# Matchers
collection:foo|<collection:"foo">
collection:foo AND bar|(<collection:"foo"> AND <text:"bar">)
collection:foo bar|(<collection:"foo"> AND <text:"bar">)
database:foo|<database:"foo">
database:foo AND bar|(<database:"foo"> AND <text:"bar">)
database:foo bar|(<database:"foo"> AND <text:"bar">)
type:foo|<media_type:"foo">
type:foo AND bar|(<media_type:"foo"> AND <text:"bar">)
type:foo bar|(<media_type:"foo"> AND <text:"bar">)
id:90|<record_identifier:"90">
id:90 AND foo|(<record_identifier:"90"> AND <text:"foo">)
id:90 foo|(<record_identifier:"90"> AND <text:"foo">)
recordid:90|<record_identifier:"90">

# Timestamps yyyy
created_on < "2015"|<range:creation lt="2015">
created_on ≤ "2015"|<range:creation lte="2015">
created_on = "2015"|<range:creation gte="2015-01-01 00:00:00" lt="2016-01-01 00:00:00">
created_on ≥ "2015"|<range:creation gte="2015">
created_on > "2015"|<range:creation gt="2015">
updated_on < "2015"|<range:update lt="2015">
updated_on ≤ "2015"|<range:update lte="2015">
updated_on = "2015"|<range:update gte="2015-01-01 00:00:00" lt="2016-01-01 00:00:00">
updated_on ≥ "2015"|<range:update gte="2015">
updated_on > "2015"|<range:update gt="2015">
created_at > "2015"|<range:creation gt="2015">
updated_at > "2015"|<range:update gt="2015">

# Timestamps yyyy/mm
created_on < "2015/01"|<range:creation lt="2015-01">
created_on ≤ "2015/01"|<range:creation lte="2015-01">
created_on = "2015/01"|<range:creation gte="2015-01-01 00:00:00" lt="2015-02-01 00:00:00">
created_on ≥ "2015/01"|<range:creation gte="2015-01">
created_on > "2015/01"|<range:creation gt="2015-01">
updated_on < "2015/01"|<range:update lt="2015-01">
updated_on ≤ "2015/01"|<range:update lte="2015-01">
updated_on = "2015/01"|<range:update gte="2015-01-01 00:00:00" lt="2015-02-01 00:00:00">
updated_on ≥ "2015/01"|<range:update gte="2015-01">
updated_on > "2015/01"|<range:update gt="2015-01">
created_at > "2015/01"|<range:creation gt="2015-01">
updated_at > "2015/01"|<range:update gt="2015-01">

# Timestamps yyyy/mm/dd
created_on < "2015/01/01"|<range:creation lt="2015-01-01">
created_on ≤ "2015/01/01"|<range:creation lte="2015-01-01">
created_on = "2015/01/01"|<range:creation gte="2015-01-01 00:00:00" lt="2015-01-02 00:00:00">
created_on ≥ "2015/01/01"|<range:creation gte="2015-01-01">
created_on > "2015/01/01"|<range:creation gt="2015-01-01">
updated_on < "2015/01/01"|<range:update lt="2015-01-01">
updated_on ≤ "2015/01/01"|<range:update lte="2015-01-01">
updated_on = "2015/01/01"|<range:update gte="2015-01-01 00:00:00" lt="2015-01-02 00:00:00">
updated_on ≥ "2015/01/01"|<range:update gte="2015-01-01">
updated_on > "2015/01/01"|<range:update gt="2015-01-01">
created_at > "2015/01/01"|<range:creation gt="2015-01-01">
updated_at > "2015/01/01"|<range:update gt="2015-01-01">

# Timestamps yyyy/mm/dd hh
created_on < "2015/01/01 12"|<range:creation lt="2015-01-01 12:00:00">
created_on ≤ "2015/01/01 12"|<range:creation lte="2015-01-01 12:00:00">
created_on = "2015/01/01 12"|<range:creation gte="2015-01-01 12:00:00" lt="2015-01-01 13:00:00">
created_on ≥ "2015/01/01 12"|<range:creation gte="2015-01-01 12:00:00">
created_on > "2015/01/01 12"|<range:creation gt="2015-01-01 12:00:00">
updated_on < "2015/01/01 12"|<range:update lt="2015-01-01 12:00:00">
updated_on ≤ "2015/01/01 12"|<range:update lte="2015-01-01 12:00:00">
updated_on = "2015/01/01 12"|<range:update gte="2015-01-01 12:00:00" lt="2015-01-01 13:00:00">
updated_on ≥ "2015/01/01 12"|<range:update gte="2015-01-01 12:00:00">
updated_on > "2015/01/01 12"|<range:update gt="2015-01-01 12:00:00">
created_at > "2015/01/01 12"|<range:creation gt="2015-01-01 12:00:00">
updated_at > "2015/01/01 12"|<range:update gt="2015-01-01 12:00:00">

# Timestamps yyyy/mm/dd hh:mm
created_on < "2015/01/01 12.34"|<range:creation lt="2015-01-01 12:34:00">
created_on ≤ "2015/01/01 12.34"|<range:creation lte="2015-01-01 12:34:00">
created_on = "2015/01/01 12.34"|<range:creation gte="2015-01-01 12:34:00" lt="2015-01-01 12:35:00">
created_on ≥ "2015/01/01 12.34"|<range:creation gte="2015-01-01 12:34:00">
created_on > "2015/01/01 12.34"|<range:creation gt="2015-01-01 12:34:00">
updated_on < "2015/01/01 12.34"|<range:update lt="2015-01-01 12:34:00">
updated_on ≤ "2015/01/01 12.34"|<range:update lte="2015-01-01 12:34:00">
updated_on = "2015/01/01 12.34"|<range:update gte="2015-01-01 12:34:00" lt="2015-01-01 12:35:00">
updated_on ≥ "2015/01/01 12.34"|<range:update gte="2015-01-01 12:34:00">
updated_on > "2015/01/01 12.34"|<range:update gt="2015-01-01 12:34:00">
created_at > "2015/01/01 12.34"|<range:creation gt="2015-01-01 12:34:00">
updated_at > "2015/01/01 12.34"|<range:update gt="2015-01-01 12:34:00">

# Timestamps yyyy/mm/dd hh.mm.ss
created_on < "2015/01/01 12.34.56"|<range:creation lt="2015-01-01 12:34:56">
created_on ≤ "2015/01/01 12.34.56"|<range:creation lte="2015-01-01 12:34:56">
created_on = "2015/01/01 12.34.56"|(<creation> == <value:"2015-01-01 12:34:56">)
created_on ≥ "2015/01/01 12.34.56"|<range:creation gte="2015-01-01 12:34:56">
created_on > "2015/01/01 12.34.56"|<range:creation gt="2015-01-01 12:34:56">
updated_on < "2015/01/01 12.34.56"|<range:update lt="2015-01-01 12:34:56">
updated_on ≤ "2015/01/01 12.34.56"|<range:update lte="2015-01-01 12:34:56">
updated_on = "2015/01/01 12.34.56"|(<update> == <value:"2015-01-01 12:34:56">)
updated_on ≥ "2015/01/01 12.34.56"|<range:update gte="2015-01-01 12:34:56">
updated_on > "2015/01/01 12.34.56"|<range:update gt="2015-01-01 12:34:56">
created_at > "2015/01/01 12.34.56"|<range:creation gt="2015-01-01 12:34:56">
updated_at > "2015/01/01 12.34.56"|<range:update gt="2015-01-01 12:34:56">

# timestamps missing zeros
created_on = "2015/1/2 1.3.5"|(<creation> == <value:"2015-01-02 01:03:05">)


# Flag matcher
flag.foo:true|<flag:foo set>
flag.foo:1|<flag:foo set>
flag.foo:false|<flag:foo cleared>
flag.foo:0|<flag:foo cleared>
flag.true:true|<flag:true set>
flag.foo bar:true|(<text:"flag.foo"> AND (<field:bar> MATCHES <text:"true">))
true|<text:"true">

# Metadata (EXIF or anything else) matcher
meta.MimeType:image/jpeg|<metadata.MimeType:"image/jpeg">
exif.MimeType:image/jpeg|<metadata.MimeType:"image/jpeg">
meta.Duration < 300|<range:metadata.Duration lt="300">
meta.Duration ≤ 300|<range:metadata.Duration lte="300">
meta.Duration > 300|<range:metadata.Duration gt="300">
meta.Duration ≥ 300|<range:metadata.Duration gte="300">
meta.Duration = 300|(<metadata.Duration> == <value:"300">)

# Unescaped "." issue on key prefixes
fieldOne:foo|(<field:fieldOne> MATCHES <text:"foo">)
flagged:true|(<field:flagged> MATCHES <text:"true">)
metadata:foo|(<field:metadata> MATCHES <text:"foo">)

# Matcher on unknown name --> fulltext
foo:bar|(<field:foo> MATCHES <text:"bar">)
foo:bar AND baz|((<field:foo> MATCHES <text:"bar">) AND <text:"baz">)
foo AND bar:baz|(<text:"foo"> AND (<field:bar> MATCHES <text:"baz">))

# Search terms with embedded keywords
INA|<text:"INA">
INA OREO|<text:"INA OREO">
ARGENT OR (MÉTAUX PRECIEUX)|(<text:"ARGENT"> OR <text:"MÉTAUX PRECIEUX">)
# ARGENT OR (MÉTAUX PRECIEUX)|<text:"ARGENT OR" context:"MÉTAUX PRECIEUX">
# ARGENT OR (MÉTAUX PRECIEUX)|(<text:"ARGENT"> AND <text:"OR" context:"MÉTAUX PRECIEUX">)
