Page MenuHomePhabricator
Paste P6895

ref impl
ActivePublic

Authored by dcausse on Mar 23 2018, 5:43 PM.
Tags
None
Referenced Files
F16003832: ref impl
Mar 23 2018, 6:46 PM
F16003135: ref impl
Mar 23 2018, 5:43 PM
Subscribers
None
{
"empty: produce an empty tree": {
"query": "",
"expected": {
"query": "",
"rawQuery": "",
"root": {
"empty": {
"startOffset": 0,
"endOffset": 0
}
}
}
},
"empty: space only produce an empty tree": {
"query": "\t\u0000 \u3000\ufeff",
"expected": {
"query": "\t\u0000 \u3000\ufeff",
"rawQuery": "\t\u0000 \u3000\ufeff",
"root": {
"empty": {
"startOffset": 0,
"endOffset": 9
}
}
}
},
"words: single word": {
"query": "word",
"expected": {
"query": "word",
"rawQuery": "word",
"root": {
"words": {
"startOffset": 0,
"endOffset": 4,
"words": "word"
}
}
}
},
"words: parenthesis are simple words": {
"query": "Louise Michel (Anachiste)",
"expected": {
"query": "Louise Michel (Anachiste)",
"rawQuery": "Louise Michel (Anachiste)",
"root": {
"words": {
"startOffset": 0,
"endOffset": 25,
"words": "Louise Michel (Anachiste)"
}
}
}
},
"words: parenthesis cannot be used yet to group boolean": {
"query": "(word1 OR word2) AND (word3 OR word4)",
"expected": {
"query": "(word1 OR word2) AND (word3 OR word4)",
"rawQuery": "(word1 OR word2) AND (word3 OR word4)",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 37,
"clauses": [
{
"SHOULD": {
"words": {
"startOffset": 0,
"endOffset": 6,
"words": "(word1"
}
},
"explicit": true
},
{
"MUST": {
"words": {
"startOffset": 10,
"endOffset": 16,
"words": "word2)"
}
},
"explicit": true
},
{
"SHOULD": {
"words": {
"startOffset": 21,
"endOffset": 27,
"words": "(word3"
}
},
"explicit": true
},
{
"SHOULD": {
"words": {
"startOffset": 31,
"endOffset": 37,
"words": "word4)"
}
},
"explicit": true
}
]
}
}
}
},
"words: multiple words are collapsed": {
"query": "word1 word2",
"expected": {
"query": "word1 word2",
"rawQuery": "word1 word2",
"root": {
"words": {
"startOffset": 0,
"endOffset": 11,
"words": "word1 word2"
}
}
}
},
"words: question mark stripping won't messup simple questions": {
"query": "how old is fred?",
"config": {
"CirrusSearchStripQuestionMarks": "all"
},
"expected": {
"query": "how old is fred ",
"rawQuery": "how old is fred?",
"queryCleanups": {
"stripped_qmark": true
},
"root": {
"words": {
"startOffset": 0,
"endOffset": 15,
"words": "how old is fred"
}
}
}
},
"words: expert users can bypass question mark stripping": {
"query": "201\\?",
"config": {
"CirrusSearchStripQuestionMarks": "all"
},
"expected": {
"query": "201?",
"rawQuery": "201\\?",
"queryCleanups": {
"stripped_qmark": true
},
"root": {
"wildcard": {
"startOffset": 0,
"endOffset": 4,
"wildcardquery": "201?"
}
}
}
},
"words: \\ can escape parsed operators": {
"query": "\\AND \\\" \\NOT \\!word word\\* word\\",
"expected": {
"query": "\\AND \\\" \\NOT \\!word word\\* word\\",
"rawQuery": "\\AND \\\" \\NOT \\!word word\\* word\\",
"root": {
"words": {
"startOffset": 0,
"endOffset": 32,
"words": "AND \" NOT !word word* word\\"
}
}
}
},
"words: tokenized on all unicode spaces and control chars": {
"query": "w1\t-w2\u3000-w3\ufeff-w4\u0000-w5",
"expected": {
"query": "w1\t-w2\u3000-w3\ufeff-w4\u0000-w5",
"rawQuery": "w1\t-w2\u3000-w3\ufeff-w4\u0000-w5",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 22,
"clauses": [
{
"MUST": {
"words": {
"startOffset": 0,
"endOffset": 2,
"words": "w1"
}
},
"explicit": false
},
{
"MUST_NOT": {
"words": {
"startOffset": 4,
"endOffset": 6,
"words": "w2"
}
},
"explicit": false
},
{
"MUST_NOT": {
"words": {
"startOffset": 10,
"endOffset": 12,
"words": "w3"
}
},
"explicit": false
},
{
"MUST_NOT": {
"words": {
"startOffset": 16,
"endOffset": 18,
"words": "w4"
}
},
"explicit": false
},
{
"MUST_NOT": {
"words": {
"startOffset": 20,
"endOffset": 22,
"words": "w5"
}
},
"explicit": false
}
]
}
}
}
},
"negation prefix: a single word can be negated with !": {
"query": "!word1",
"expected": {
"query": "!word1",
"rawQuery": "!word1",
"root": {
"bool": {
"startOffset": 1,
"endOffset": 6,
"clauses": [
{
"MUST_NOT": {
"words": {
"startOffset": 1,
"endOffset": 6,
"words": "word1"
}
},
"explicit": false
}
]
}
}
}
},
"negation prefix: a single word can be negated with -": {
"query": "-word1",
"expected": {
"query": "-word1",
"rawQuery": "-word1",
"root": {
"bool": {
"startOffset": 1,
"endOffset": 6,
"clauses": [
{
"MUST_NOT": {
"words": {
"startOffset": 1,
"endOffset": 6,
"words": "word1"
}
},
"explicit": false
}
]
}
}
}
},
"negation prefix: - won't split words": {
"query": "foo-bar",
"expected": {
"query": "foo-bar",
"rawQuery": "foo-bar",
"root": {
"words": {
"startOffset": 0,
"endOffset": 7,
"words": "foo-bar"
}
}
}
},
"negation prefix: ! won't split words": {
"query": "foo!bar",
"expected": {
"query": "foo!bar",
"rawQuery": "foo!bar",
"root": {
"words": {
"startOffset": 0,
"endOffset": 7,
"words": "foo!bar"
}
}
}
},
"negation prefix: a single word can be explicitily negated with NOT": {
"query": "NOT word1",
"expected": {
"query": "NOT word1",
"rawQuery": "NOT word1",
"root": {
"bool": {
"startOffset": 4,
"endOffset": 9,
"clauses": [
{
"MUST_NOT": {
"words": {
"startOffset": 4,
"endOffset": 9,
"words": "word1"
}
},
"explicit": true
}
]
}
}
}
},
"negation prefix: words are not collapsed when one is negated": {
"query": "word0 !word1 word1",
"expected": {
"query": "word0 !word1 word1",
"rawQuery": "word0 !word1 word1",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 18,
"clauses": [
{
"MUST": {
"words": {
"startOffset": 0,
"endOffset": 5,
"words": "word0"
}
},
"explicit": false
},
{
"MUST_NOT": {
"words": {
"startOffset": 7,
"endOffset": 12,
"words": "word1"
}
},
"explicit": false
},
{
"MUST": {
"words": {
"startOffset": 13,
"endOffset": 18,
"words": "word1"
}
},
"explicit": false
}
]
}
}
}
},
"negation prefix: ! negation is ignored on non letters": {
"query": "!@word1",
"expected": {
"query": "!@word1",
"rawQuery": "!@word1",
"root": {
"words": {
"startOffset": 0,
"endOffset": 7,
"words": "!@word1"
}
}
}
},
"negation prefix: - negation is ignored on non letters": {
"query": "-@word1",
"expected": {
"query": "-@word1",
"rawQuery": "-@word1",
"root": {
"words": {
"startOffset": 0,
"endOffset": 7,
"words": "-@word1"
}
}
}
},
"negation: NOT negation is not ignored on non letters": {
"query": "NOT @word1",
"expected": {
"query": "NOT @word1",
"rawQuery": "NOT @word1",
"root": {
"bool": {
"startOffset": 4,
"endOffset": 10,
"clauses": [
{
"MUST_NOT": {
"words": {
"startOffset": 4,
"endOffset": 10,
"words": "@word1"
}
},
"explicit": true
}
]
}
}
}
},
"bool: simple AND between words with AND": {
"query": "word1 AND word2",
"expected": {
"query": "word1 AND word2",
"rawQuery": "word1 AND word2",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 15,
"clauses": [
{
"MUST": {
"words": {
"startOffset": 0,
"endOffset": 5,
"words": "word1"
}
},
"explicit": true
},
{
"MUST": {
"words": {
"startOffset": 10,
"endOffset": 15,
"words": "word2"
}
},
"explicit": true
}
]
}
}
}
},
"bool: simple AND between words with &&": {
"query": "word1 && word2",
"expected": {
"query": "word1 && word2",
"rawQuery": "word1 && word2",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 14,
"clauses": [
{
"MUST": {
"words": {
"startOffset": 0,
"endOffset": 5,
"words": "word1"
}
},
"explicit": true
},
{
"MUST": {
"words": {
"startOffset": 9,
"endOffset": 14,
"words": "word2"
}
},
"explicit": true
}
]
}
}
}
},
"bool: simple OR between words with OR": {
"query": "word1 OR word2",
"expected": {
"query": "word1 OR word2",
"rawQuery": "word1 OR word2",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 14,
"clauses": [
{
"SHOULD": {
"words": {
"startOffset": 0,
"endOffset": 5,
"words": "word1"
}
},
"explicit": true
},
{
"SHOULD": {
"words": {
"startOffset": 9,
"endOffset": 14,
"words": "word2"
}
},
"explicit": true
}
]
}
}
}
},
"bool: simple OR between words with ||": {
"query": "word1 || word2",
"expected": {
"query": "word1 || word2",
"rawQuery": "word1 || word2",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 14,
"clauses": [
{
"SHOULD": {
"words": {
"startOffset": 0,
"endOffset": 5,
"words": "word1"
}
},
"explicit": true
},
{
"SHOULD": {
"words": {
"startOffset": 9,
"endOffset": 14,
"words": "word2"
}
},
"explicit": true
}
]
}
}
}
},
"bool: backward order precedence MUST:word1 SHOULD:word2 SHOULD:word3": {
"query": "word1 AND word2 OR word3",
"expected": {
"query": "word1 AND word2 OR word3",
"rawQuery": "word1 AND word2 OR word3",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 24,
"clauses": [
{
"MUST": {
"words": {
"startOffset": 0,
"endOffset": 5,
"words": "word1"
}
},
"explicit": true
},
{
"SHOULD": {
"words": {
"startOffset": 10,
"endOffset": 15,
"words": "word2"
}
},
"explicit": true
},
{
"SHOULD": {
"words": {
"startOffset": 19,
"endOffset": 24,
"words": "word3"
}
},
"explicit": true
}
]
}
}
}
},
"bool: backward order precedence SHOULD:word1 MUST:word2 MUST:word3": {
"query": "word1 OR word2 AND word3",
"expected": {
"query": "word1 OR word2 AND word3",
"rawQuery": "word1 OR word2 AND word3",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 24,
"clauses": [
{
"SHOULD": {
"words": {
"startOffset": 0,
"endOffset": 5,
"words": "word1"
}
},
"explicit": true
},
{
"MUST": {
"words": {
"startOffset": 9,
"endOffset": 14,
"words": "word2"
}
},
"explicit": true
},
{
"MUST": {
"words": {
"startOffset": 19,
"endOffset": 24,
"words": "word3"
}
},
"explicit": true
}
]
}
}
}
},
"bool & negation: AND NOT is comprehensive": {
"query": "word1 AND NOT word2",
"expected": {
"query": "word1 AND NOT word2",
"rawQuery": "word1 AND NOT word2",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 19,
"clauses": [
{
"MUST": {
"words": {
"startOffset": 0,
"endOffset": 5,
"words": "word1"
}
},
"explicit": true
},
{
"MUST_NOT": {
"words": {
"startOffset": 14,
"endOffset": 19,
"words": "word2"
}
},
"explicit": true
}
]
}
}
}
},
"bool & negation: OR NOT is obscure in search bool (SHOULD_NOT does not exist)": {
"query": "word1 OR NOT word2",
"expected": {
"query": "word1 OR NOT word2",
"rawQuery": "word1 OR NOT word2",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 18,
"clauses": [
{
"SHOULD": {
"words": {
"startOffset": 0,
"endOffset": 5,
"words": "word1"
}
},
"explicit": true
},
{
"MUST_NOT": {
"words": {
"startOffset": 13,
"endOffset": 18,
"words": "word2"
}
},
"explicit": true
}
]
}
}
}
},
"phrase: simple phrase": {
"query": "\"word1 word2\"",
"expected": {
"query": "\"word1 word2\"",
"rawQuery": "\"word1 word2\"",
"root": {
"phrase": {
"startOffset": 0,
"endOffset": 13,
"phrase": "word1 word2",
"slop": -1,
"stem": false,
"unbalanced": false
}
}
}
},
"phrase: phrase can include uninterepreted negation prefix": {
"query": "\"!happy\" \"-happy\" happy",
"expected": {
"query": "\"!happy\" \"-happy\" happy",
"rawQuery": "\"!happy\" \"-happy\" happy",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 23,
"clauses": [
{
"MUST": {
"phrase": {
"startOffset": 0,
"endOffset": 8,
"phrase": "!happy",
"slop": -1,
"stem": false,
"unbalanced": false
}
},
"explicit": false
},
{
"MUST": {
"phrase": {
"startOffset": 9,
"endOffset": 17,
"phrase": "-happy",
"slop": -1,
"stem": false,
"unbalanced": false
}
},
"explicit": false
},
{
"MUST": {
"words": {
"startOffset": 18,
"endOffset": 23,
"words": "happy"
}
},
"explicit": false
}
]
}
}
}
},
"phrase: simple phrase on stems": {
"query": "\"word1 word2\"~",
"expected": {
"query": "\"word1 word2\"~",
"rawQuery": "\"word1 word2\"~",
"root": {
"phrase": {
"startOffset": 0,
"endOffset": 14,
"phrase": "word1 word2",
"slop": -1,
"stem": true,
"unbalanced": false
}
}
}
},
"phrase: simple phrase with 0 slop": {
"query": "\"word1 word2\"~0",
"expected": {
"query": "\"word1 word2\"~0",
"rawQuery": "\"word1 word2\"~0",
"root": {
"phrase": {
"startOffset": 0,
"endOffset": 15,
"phrase": "word1 word2",
"slop": 0,
"stem": false,
"unbalanced": false
}
}
}
},
"phrase: simple phrase with 1 slop": {
"query": "\"word1 word2\"~1",
"expected": {
"query": "\"word1 word2\"~1",
"rawQuery": "\"word1 word2\"~1",
"root": {
"phrase": {
"startOffset": 0,
"endOffset": 15,
"phrase": "word1 word2",
"slop": 1,
"stem": false,
"unbalanced": false
}
}
}
},
"phrase: simple phrase on stems with 0 slop": {
"query": "\"word1 word2\"~0~",
"expected": {
"query": "\"word1 word2\"~0~",
"rawQuery": "\"word1 word2\"~0~",
"root": {
"phrase": {
"startOffset": 0,
"endOffset": 16,
"phrase": "word1 word2",
"slop": 0,
"stem": true,
"unbalanced": false
}
}
}
},
"phrase: simple phrase on stems with 1 slop": {
"query": "\"word1 word2\"~1~",
"expected": {
"query": "\"word1 word2\"~1~",
"rawQuery": "\"word1 word2\"~1~",
"root": {
"phrase": {
"startOffset": 0,
"endOffset": 16,
"phrase": "word1 word2",
"slop": 1,
"stem": true,
"unbalanced": false
}
}
}
},
"phrase prefix: simple phrase prefix": {
"query": "\"word1 word2*\"",
"expected": {
"query": "\"word1 word2*\"",
"rawQuery": "\"word1 word2*\"",
"root": {
"phrase_prefix": {
"startOffset": 0,
"endOffset": 14,
"phrase": "word1 word2"
}
}
}
},
"phrase prefix: phrase prefix does not support stem": {
"query": "\"word1 word2*\"~",
"expected": {
"query": "\"word1 word2*\"~",
"rawQuery": "\"word1 word2*\"~",
"root": {
"phrase": {
"startOffset": 0,
"endOffset": 15,
"phrase": "word1 word2*",
"slop": -1,
"stem": true,
"unbalanced": false
}
}
}
},
"phrase prefix: phrase prefix does not support stem & slop": {
"query": "\"word1 word2*\"~1~",
"expected": {
"query": "\"word1 word2*\"~1~",
"rawQuery": "\"word1 word2*\"~1~",
"root": {
"phrase": {
"startOffset": 0,
"endOffset": 17,
"phrase": "word1 word2*",
"slop": 1,
"stem": true,
"unbalanced": false
}
}
}
},
"phrase prefix: phrase prefix does not support slop": {
"query": "\"word1 word2*\"~2",
"expected": {
"query": "\"word1 word2*\"~2",
"rawQuery": "\"word1 word2*\"~2",
"root": {
"phrase": {
"startOffset": 0,
"endOffset": 16,
"phrase": "word1 word2*",
"slop": 2,
"stem": false,
"unbalanced": false
}
}
}
},
"phrase and words: words can be callapsed to phrase begining and ending": {
"query": "foo\"bar\"baz",
"expected": {
"query": "foo\"bar\"baz",
"rawQuery": "foo\"bar\"baz",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 11,
"clauses": [
{
"MUST": {
"words": {
"startOffset": 0,
"endOffset": 3,
"words": "foo"
}
},
"explicit": false
},
{
"MUST": {
"phrase": {
"startOffset": 3,
"endOffset": 8,
"phrase": "bar",
"slop": -1,
"stem": false,
"unbalanced": false
}
},
"explicit": false
},
{
"MUST": {
"words": {
"startOffset": 8,
"endOffset": 11,
"words": "baz"
}
},
"explicit": false
}
]
}
}
}
},
"phrase and words: hebrew has special quirks for gershayim": {
"query": "foo\"b",
"config": {
"LanguageCode": "he"
},
"expected": {
"query": "foo\\\"b",
"rawQuery": "foo\"b",
"queryCleanups": {
"gershayim_quirks": true
},
"root": {
"words": {
"startOffset": 0,
"endOffset": 6,
"words": "foo\"b"
}
}
}
},
"bool and phrase: boolean within phrase are not interpreted": {
"query": "\"foo AND NOT bar OR baz\"",
"expected": {
"query": "\"foo AND NOT bar OR baz\"",
"rawQuery": "\"foo AND NOT bar OR baz\"",
"root": {
"phrase": {
"startOffset": 0,
"endOffset": 24,
"phrase": "foo AND NOT bar OR baz",
"slop": -1,
"stem": false,
"unbalanced": false
}
}
}
},
"bool and phrase: boolean operator can be collapsed with phrase like words (debatable)": {
"query": "foo OR\"bar baz\"OR buz",
"expected": {
"query": "foo OR\"bar baz\"OR buz",
"rawQuery": "foo OR\"bar baz\"OR buz",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 21,
"clauses": [
{
"SHOULD": {
"words": {
"startOffset": 0,
"endOffset": 3,
"words": "foo"
}
},
"explicit": true
},
{
"SHOULD": {
"phrase": {
"startOffset": 6,
"endOffset": 15,
"phrase": "bar baz",
"slop": -1,
"stem": false,
"unbalanced": false
}
},
"explicit": true
},
{
"SHOULD": {
"words": {
"startOffset": 18,
"endOffset": 21,
"words": "buz"
}
},
"explicit": true
}
]
}
}
}
},
"boolean: bool operators cannot be collapsed with negation prefix": {
"query": "foo AND-bar NOT!baz",
"expected": {
"query": "foo AND-bar NOT!baz",
"rawQuery": "foo AND-bar NOT!baz",
"root": {
"words": {
"startOffset": 0,
"endOffset": 19,
"words": "foo AND-bar NOT!baz"
}
}
}
},
"fuzzy: simple fuzzy word": {
"query": "word~",
"expected": {
"query": "word~",
"rawQuery": "word~",
"root": {
"words": {
"startOffset": 0,
"endOffset": 5,
"words": "word~"
}
}
}
},
"fuzzy: fuzzy word with explicit distance": {
"query": "word~0 2word~1 word~2",
"expected": {
"query": "word~0 2word~1 word~2",
"rawQuery": "word~0 2word~1 word~2",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 21,
"clauses": [
{
"MUST": {
"fuzzy": {
"startOffset": 0,
"endOffset": 6,
"word": "word",
"fuzziness": 1
}
},
"explicit": false
},
{
"MUST": {
"fuzzy": {
"startOffset": 7,
"endOffset": 14,
"word": "2word",
"fuzziness": 1
}
},
"explicit": false
},
{
"MUST": {
"fuzzy": {
"startOffset": 15,
"endOffset": 21,
"word": "word",
"fuzziness": 1
}
},
"explicit": false
}
]
}
}
}
},
"fuzzy: fuzzy markup is ignored on non letters\/numbers and invalid distance": {
"query": "w@rd~ w-ord~1 word~.9 word~a ~",
"expected": {
"query": "w@rd~ w-ord~1 word~.9 word~a ~",
"rawQuery": "w@rd~ w-ord~1 word~.9 word~a ~",
"root": {
"words": {
"startOffset": 0,
"endOffset": 30,
"words": "w@rd~ w-ord~1 word~.9 word~a ~"
}
}
}
},
"prefix: only letters and numbers are allowed": {
"query": "1* 1w** @notaprefix*",
"expected": {
"query": "1* 1w** @notaprefix*",
"rawQuery": "1* 1w** @notaprefix*",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 20,
"clauses": [
{
"MUST": {
"prefix": [
{
"startOffset": 0,
"endOffset": 2,
"prefix": "1"
}
]
},
"explicit": false
},
{
"MUST": {
"prefix": [
{
"startOffset": 3,
"endOffset": 7,
"prefix": "1w"
}
]
},
"explicit": false
},
{
"MUST": {
"words": {
"startOffset": 8,
"endOffset": 20,
"words": "@notaprefix*"
}
},
"explicit": false
}
]
}
}
}
},
"wildcard (leading allowed): only letters and numbers (3 non contiguous wildcard max)": {
"query": "*w* *1?2*3 *@not*a*wildcard no?*awildcard",
"config": {
"CirrusSearchStripQuestionMarks": "none",
"CirrusSearchAllowLeadingWildcard": true
},
"expected": {
"query": "*w* *1?2*3 *@not*a*wildcard no?*awildcard",
"rawQuery": "*w* *1?2*3 *@not*a*wildcard no?*awildcard",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 41,
"clauses": [
{
"MUST": {
"wildcard": {
"startOffset": 0,
"endOffset": 3,
"wildcardquery": "*w*"
}
},
"explicit": false
},
{
"MUST": {
"wildcard": {
"startOffset": 4,
"endOffset": 10,
"wildcardquery": "*1?2*3"
}
},
"explicit": false
},
{
"MUST": {
"words": {
"startOffset": 11,
"endOffset": 27,
"words": "*@not*a*wildcard"
}
},
"explicit": false
},
{
"MUST": {
"wildcard": {
"startOffset": 28,
"endOffset": 41,
"wildcardquery": "no?*awildcard"
}
},
"explicit": false
}
]
}
}
}
},
"wildcard (leading not allowed): only letters and numbers (3 wildcard max)": {
"query": "*w* *1?2*3 1*2*3*4* *@not*a*wildcard",
"config": {
"CirrusSearchStripQuestionMarks": "none",
"CirrusSearchAllowLeadingWildcard": false
},
"expected": {
"query": "*w* *1?2*3 1*2*3*4* *@not*a*wildcard",
"rawQuery": "*w* *1?2*3 1*2*3*4* *@not*a*wildcard",
"root": {
"words": {
"startOffset": 0,
"endOffset": 36,
"words": "*w* *1?2*3 1*2*3*4* *@not*a*wildcard"
}
}
}
},
"keyword headings: is parsed if at the beginning (incl leading spaces)": {
"query": " local:word",
"expected": {
"query": " local:word",
"rawQuery": " local:word",
"root": {
"bool": {
"startOffset": 2,
"endOffset": 12,
"clauses": [
{
"MUST": {
"keyword": {
"startOffset": 2,
"endOffset": 8,
"keyword": "CirrusSearch\\Query\\LocalFeature",
"key": "local",
"value": "",
"quotedValue": "",
"delimiter": "",
"suffix": ""
}
},
"explicit": false
},
{
"MUST": {
"words": {
"startOffset": 8,
"endOffset": 12,
"words": "word"
}
},
"explicit": false
}
]
}
}
}
},
"keyword headings: is parsed if at the beginning": {
"query": "local:word",
"expected": {
"query": "local:word",
"rawQuery": "local:word",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 10,
"clauses": [
{
"MUST": {
"keyword": {
"startOffset": 0,
"endOffset": 6,
"keyword": "CirrusSearch\\Query\\LocalFeature",
"key": "local",
"value": "",
"quotedValue": "",
"delimiter": "",
"suffix": ""
}
},
"explicit": false
},
{
"MUST": {
"words": {
"startOffset": 6,
"endOffset": 10,
"words": "word"
}
},
"explicit": false
}
]
}
}
}
},
"keyword value: valued keywords can accept a space": {
"query": "intitle: word",
"expected": {
"query": "intitle: word",
"rawQuery": "intitle: word",
"root": {
"keyword": {
"startOffset": 0,
"endOffset": 13,
"keyword": "CirrusSearch\\Query\\InTitleFeature",
"key": "intitle",
"value": "word",
"quotedValue": "word",
"delimiter": "",
"suffix": ""
}
}
}
},
"keyword value: valued keywords are ignored if no value is provided": {
"query": "intitle: ",
"expected": {
"query": "intitle: ",
"rawQuery": "intitle: ",
"root": {
"words": {
"startOffset": 0,
"endOffset": 8,
"words": "intitle:"
}
}
}
},
"keyword unvalued: some non heading keywords accepts no value": {
"query": "foo prefer-recent:",
"expected": {
"query": "foo prefer-recent:",
"rawQuery": "foo prefer-recent:",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 18,
"clauses": [
{
"MUST": {
"words": {
"startOffset": 0,
"endOffset": 3,
"words": "foo"
}
},
"explicit": false
},
{
"MUST": {
"keyword": {
"startOffset": 4,
"endOffset": 18,
"keyword": "CirrusSearch\\Query\\PreferRecentFeature",
"key": "prefer-recent",
"value": "",
"quotedValue": "",
"delimiter": "",
"suffix": ""
}
},
"explicit": false
}
]
}
}
}
},
"keyword greedy: greedy keywords eat no matter what is written after them": {
"query": "prefix:test intitle:test",
"expected": {
"query": "prefix:test intitle:test",
"rawQuery": "prefix:test intitle:test",
"root": {
"keyword": {
"startOffset": 0,
"endOffset": 24,
"keyword": "CirrusSearch\\Query\\PrefixFeature",
"key": "prefix",
"value": "test intitle:test",
"quotedValue": "test intitle:test",
"delimiter": "",
"suffix": ""
}
}
}
},
"keyword greedy headings: greedy headings keywords eat no matter what is written after them": {
"query": "morelike: prefix:test intitle:test",
"expected": {
"query": "morelike: prefix:test intitle:test",
"rawQuery": "morelike: prefix:test intitle:test",
"root": {
"keyword": {
"startOffset": 0,
"endOffset": 34,
"keyword": "CirrusSearch\\Query\\MoreLikeFeature",
"key": "morelike",
"value": "prefix:test intitle:test",
"quotedValue": "prefix:test intitle:test",
"delimiter": "",
"suffix": ""
}
}
}
},
"keyword greedy headings: greedy headings keywords are ignored when not at the begining": {
"query": "foo morelike:baz",
"expected": {
"query": "foo morelike:baz",
"rawQuery": "foo morelike:baz",
"root": {
"words": {
"startOffset": 0,
"endOffset": 16,
"words": "foo morelike:baz"
}
}
}
},
"keyword headings: heading is not parsed when in the middle": {
"query": "word local:word",
"expected": {
"query": "word local:word",
"rawQuery": "word local:word",
"root": {
"words": {
"startOffset": 0,
"endOffset": 15,
"words": "word local:word"
}
}
}
},
"keyword : normal keyword can appear at the begining or after a space": {
"query": "intitle:foo word intitle:bar",
"expected": {
"query": "intitle:foo word intitle:bar",
"rawQuery": "intitle:foo word intitle:bar",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 28,
"clauses": [
{
"MUST": {
"keyword": {
"startOffset": 0,
"endOffset": 11,
"keyword": "CirrusSearch\\Query\\InTitleFeature",
"key": "intitle",
"value": "foo",
"quotedValue": "foo",
"delimiter": "",
"suffix": ""
}
},
"explicit": false
},
{
"MUST": {
"words": {
"startOffset": 12,
"endOffset": 16,
"words": "word"
}
},
"explicit": false
},
{
"MUST": {
"keyword": {
"startOffset": 17,
"endOffset": 28,
"keyword": "CirrusSearch\\Query\\InTitleFeature",
"key": "intitle",
"value": "bar",
"quotedValue": "bar",
"delimiter": "",
"suffix": ""
}
},
"explicit": false
}
]
}
}
}
},
"keyword : normal usually accept a quoted value": {
"query": "intitle:\"foo \"bar baz\"",
"expected": {
"query": "intitle:\"foo \"bar baz\"",
"rawQuery": "intitle:\"foo \"bar baz\"",
"warnings": [
{
"msg": "cirrus-parse-error-unbalanced-phrase",
"start": 21
}
],
"root": {
"bool": {
"startOffset": 0,
"endOffset": 22,
"clauses": [
{
"MUST": {
"keyword": {
"startOffset": 0,
"endOffset": 14,
"keyword": "CirrusSearch\\Query\\InTitleFeature",
"key": "intitle",
"value": "foo ",
"quotedValue": "\"foo \"",
"delimiter": "\"",
"suffix": ""
}
},
"explicit": false
},
{
"MUST": {
"words": {
"startOffset": 14,
"endOffset": 21,
"words": "bar baz"
}
},
"explicit": false
},
{
"MUST": {
"phrase": {
"startOffset": 21,
"endOffset": 22,
"phrase": "",
"slop": -1,
"stem": false,
"unbalanced": true
}
},
"explicit": false
}
]
}
}
}
},
"keyword : regex is triggered with a \/ and accepts an optional suffix ": {
"query": "intitle:\/[a-z]\/ insource:\/<\\\/a>[^ ]\/i",
"expected": {
"query": "intitle:\/[a-z]\/ insource:\/<\\\/a>[^ ]\/i",
"rawQuery": "intitle:\/[a-z]\/ insource:\/<\\\/a>[^ ]\/i",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 37,
"clauses": [
{
"MUST": {
"keyword": {
"startOffset": 0,
"endOffset": 15,
"keyword": "CirrusSearch\\Query\\InTitleFeature",
"key": "intitle",
"value": "[a-z]",
"quotedValue": "\/[a-z]\/",
"delimiter": "\/",
"suffix": ""
}
},
"explicit": false
},
{
"MUST": {
"keyword": {
"startOffset": 16,
"endOffset": 37,
"keyword": "CirrusSearch\\Query\\InSourceFeature",
"key": "insource",
"value": "<\/a>[^ ]",
"quotedValue": "\/<\\\/a>[^ ]\/",
"delimiter": "\/",
"suffix": "i"
}
},
"explicit": false
}
]
}
}
}
},
"keyword : normal keyword can not appear anywhere": {
"query": "\"intitle:bar\"",
"expected": {
"query": "\"intitle:bar\"",
"rawQuery": "\"intitle:bar\"",
"root": {
"phrase": {
"startOffset": 0,
"endOffset": 13,
"phrase": "intitle:bar",
"slop": -1,
"stem": false,
"unbalanced": false
}
}
}
},
"keyword : normal keyword can not appear anywhere unlike normal words": {
"query": "\"foo bar\"intitle:bar",
"expected": {
"query": "\"foo bar\"intitle:bar",
"rawQuery": "\"foo bar\"intitle:bar",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 20,
"clauses": [
{
"MUST": {
"phrase": {
"startOffset": 0,
"endOffset": 9,
"phrase": "foo bar",
"slop": -1,
"stem": false,
"unbalanced": false
}
},
"explicit": false
},
{
"MUST": {
"words": {
"startOffset": 9,
"endOffset": 20,
"words": "intitle:bar"
}
},
"explicit": false
}
]
}
}
}
},
"keyword & negation prefix: normal keyword can be negated with - but not with ! (debatable)": {
"query": "-intitle:bar !intitle:bar",
"expected": {
"query": "-intitle:bar !intitle:bar",
"rawQuery": "-intitle:bar !intitle:bar",
"root": {
"bool": {
"startOffset": 1,
"endOffset": 25,
"clauses": [
{
"MUST_NOT": {
"keyword": {
"startOffset": 1,
"endOffset": 12,
"keyword": "CirrusSearch\\Query\\InTitleFeature",
"key": "intitle",
"value": "bar",
"quotedValue": "bar",
"delimiter": "",
"suffix": ""
}
},
"explicit": false
},
{
"MUST_NOT": {
"words": {
"startOffset": 14,
"endOffset": 25,
"words": "intitle:bar"
}
},
"explicit": false
}
]
}
}
}
},
"keywords & bool: follows normal boolean logic": {
"query": "intitle:foo AND intitle:bar OR intitle:baz OR NOT intitle:buz",
"expected": {
"query": "intitle:foo AND intitle:bar OR intitle:baz OR NOT intitle:buz",
"rawQuery": "intitle:foo AND intitle:bar OR intitle:baz OR NOT intitle:buz",
"root": {
"bool": {
"startOffset": 0,
"endOffset": 61,
"clauses": [
{
"MUST": {
"keyword": {
"startOffset": 0,
"endOffset": 11,
"keyword": "CirrusSearch\\Query\\InTitleFeature",
"key": "intitle",
"value": "foo",
"quotedValue": "foo",
"delimiter": "",
"suffix": ""
}
},
"explicit": true
},
{
"SHOULD": {
"keyword": {
"startOffset": 16,
"endOffset": 27,
"keyword": "CirrusSearch\\Query\\InTitleFeature",
"key": "intitle",
"value": "bar",
"quotedValue": "bar",
"delimiter": "",
"suffix": ""
}
},
"explicit": true
},
{
"SHOULD": {
"keyword": {
"startOffset": 31,
"endOffset": 42,
"keyword": "CirrusSearch\\Query\\InTitleFeature",
"key": "intitle",
"value": "baz",
"quotedValue": "baz",
"delimiter": "",
"suffix": ""
}
},
"explicit": true
},
{
"MUST_NOT": {
"keyword": {
"startOffset": 50,
"endOffset": 61,
"keyword": "CirrusSearch\\Query\\InTitleFeature",
"key": "intitle",
"value": "buz",
"quotedValue": "buz",
"delimiter": "",
"suffix": ""
}
},
"explicit": true
}
]
}
}
}
},
"keywords precedence: keywords take precedence over everything else": {
"query": "\" intitle:test \"",
"expected": {
"query": "\" intitle:test \"",
"rawQuery": "\" intitle:test \"",
"warnings": [
{
"msg": "cirrus-parse-error-unbalanced-phrase",
"start": 0
},
{
"msg": "cirrus-parse-error-unbalanced-phrase",
"start": 15
}
],
"root": {
"bool": {
"startOffset": 0,
"endOffset": 16,
"clauses": [
{
"MUST": {
"phrase": {
"startOffset": 0,
"endOffset": 2,
"phrase": " ",
"slop": -1,
"stem": false,
"unbalanced": true
}
},
"explicit": false
},
{
"MUST": {
"keyword": {
"startOffset": 2,
"endOffset": 14,
"keyword": "CirrusSearch\\Query\\InTitleFeature",
"key": "intitle",
"value": "test",
"quotedValue": "test",
"delimiter": "",
"suffix": ""
}
},
"explicit": false
},
{
"MUST": {
"phrase": {
"startOffset": 15,
"endOffset": 16,
"phrase": "",
"slop": -1,
"stem": false,
"unbalanced": true
}
},
"explicit": false
}
]
}
}
}
},
"fixups: unexpected bool operator is eaten as a word and produduce a warning": {
"query": "foo AND AND bar",
"expected": {
"query": "foo AND AND bar",
"rawQuery": "foo AND AND bar",
"warnings": [
{
"msg": "cirrus-parse-error-unexpected-token",
"start": 8,
"expected": [
"NOT",
"QUERY"
],
"actual": "AND"
}
],
"root": {
"bool": {
"startOffset": 0,
"endOffset": 15,
"clauses": [
{
"MUST": {
"words": {
"startOffset": 0,
"endOffset": 3,
"words": "foo"
}
},
"explicit": false
},
{
"MUST": {
"words": {
"startOffset": 8,
"endOffset": 15,
"words": "AND bar"
}
},
"explicit": true
}
]
}
}
}
},
"fixups: unexpected bool operator after NOT is eaten as a word and produduce a warning": {
"query": "foo NOT AND bar",
"expected": {
"query": "foo NOT AND bar",
"rawQuery": "foo NOT AND bar",
"warnings": [
{
"msg": "cirrus-parse-error-unexpected-token",
"start": 8,
"expected": [
"QUERY"
],
"actual": "AND"
}
],
"root": {
"bool": {
"startOffset": 0,
"endOffset": 15,
"clauses": [
{
"MUST": {
"words": {
"startOffset": 0,
"endOffset": 3,
"words": "foo"
}
},
"explicit": false
},
{
"MUST": {
"words": {
"startOffset": 8,
"endOffset": 15,
"words": "AND bar"
}
},
"explicit": false
}
]
}
}
}
},
"fixups: double explicit NOT is eaten as a word and produduce a warning": {
"query": "foo NOT NOT bar",
"expected": {
"query": "foo NOT NOT bar",
"rawQuery": "foo NOT NOT bar",
"warnings": [
{
"msg": "cirrus-parse-error-unexpected-token",
"start": 8,
"expected": [
"QUERY"
],
"actual": "NOT"
}
],
"root": {
"bool": {
"startOffset": 0,
"endOffset": 15,
"clauses": [
{
"MUST": {
"words": {
"startOffset": 0,
"endOffset": 3,
"words": "foo"
}
},
"explicit": false
},
{
"MUST": {
"words": {
"startOffset": 8,
"endOffset": 15,
"words": "NOT bar"
}
},
"explicit": false
}
]
}
}
}
},
"fixups: double negation with negation prefix is ignored and produduce a warning (debatable)": {
"query": "foo NOT -bar",
"expected": {
"query": "foo NOT -bar",
"rawQuery": "foo NOT -bar",
"warnings": [
{
"msg": "cirrus-parse-error-double-negation",
"start": 8
}
],
"root": {
"bool": {
"startOffset": 0,
"endOffset": 12,
"clauses": [
{
"MUST": {
"words": {
"startOffset": 0,
"endOffset": 3,
"words": "foo"
}
},
"explicit": false
},
{
"MUST": {
"words": {
"startOffset": 9,
"endOffset": 12,
"words": "bar"
}
},
"explicit": false
}
]
}
}
}
},
"fixups: OR at eof is eaten as a word and produduce a warning": {
"query": "foo OR ",
"expected": {
"query": "foo OR ",
"rawQuery": "foo OR ",
"warnings": [
{
"msg": "cirrus-parse-error-unexpected-eof",
"start": 7,
"expected": [
"NOT",
"QUERY"
],
"actual": "EOF"
}
],
"root": {
"words": {
"startOffset": 0,
"endOffset": 6,
"words": "foo OR"
}
}
}
},
"fixups: NOT at eof is eaten as a word and produduce a warning": {
"query": "foo NOT ",
"expected": {
"query": "foo NOT ",
"rawQuery": "foo NOT ",
"warnings": [
{
"msg": "cirrus-parse-error-unexpected-eof",
"start": 8,
"expected": [
"QUERY"
],
"actual": "EOF"
}
],
"root": {
"words": {
"startOffset": 0,
"endOffset": 7,
"words": "foo NOT"
}
}
}
},
"fixups: leading boolean operator is eaten as a word and produce a warning": {
"query": "AND foo",
"expected": {
"query": "AND foo",
"rawQuery": "AND foo",
"warnings": [
{
"msg": "cirrus-parse-error-unexpected-token",
"start": 0,
"expected": [
"NOT",
"QUERY"
],
"actual": "AND"
}
],
"root": {
"words": {
"startOffset": 0,
"endOffset": 7,
"words": "AND foo"
}
}
}
},
"fixups: unbalanced phrase are identified and produce a warning": {
"query": "foo \"bar ",
"expected": {
"query": "foo \"bar ",
"rawQuery": "foo \"bar ",
"warnings": [
{
"msg": "cirrus-parse-error-unbalanced-phrase",
"start": 4
}
],
"root": {
"bool": {
"startOffset": 0,
"endOffset": 9,
"clauses": [
{
"MUST": {
"words": {
"startOffset": 0,
"endOffset": 3,
"words": "foo"
}
},
"explicit": false
},
{
"MUST": {
"phrase": {
"startOffset": 4,
"endOffset": 9,
"phrase": "bar ",
"slop": -1,
"stem": false,
"unbalanced": true
}
},
"explicit": false
}
]
}
}
}
},
"fixups: query made of bool operator may read one bool out of 2 properly and produce a warning (debatable)": {
"query": "AND && OR OR AND && ||",
"expected": {
"query": "AND && OR OR AND && ||",
"rawQuery": "AND && OR OR AND && ||",
"warnings": [
{
"msg": "cirrus-parse-error-unexpected-token",
"start": 0,
"expected": [
"NOT",
"QUERY"
],
"actual": "AND"
},
{
"msg": "cirrus-parse-error-unexpected-token",
"start": 7,
"expected": [
"NOT",
"QUERY"
],
"actual": "OR"
},
{
"msg": "cirrus-parse-error-unexpected-token",
"start": 13,
"expected": [
"NOT",
"QUERY"
],
"actual": "AND"
},
{
"msg": "cirrus-parse-error-unexpected-token",
"start": 20,
"expected": [
"NOT",
"QUERY"
],
"actual": "OR"
}
],
"root": {
"bool": {
"startOffset": 0,
"endOffset": 22,
"clauses": [
{
"MUST": {
"words": {
"startOffset": 0,
"endOffset": 3,
"words": "AND"
}
},
"explicit": false
},
{
"MUST": {
"words": {
"startOffset": 7,
"endOffset": 9,
"words": "OR"
}
},
"explicit": false
},
{
"MUST": {
"words": {
"startOffset": 13,
"endOffset": 16,
"words": "AND"
}
},
"explicit": false
},
{
"MUST": {
"words": {
"startOffset": 20,
"endOffset": 22,
"words": "||"
}
},
"explicit": true
}
]
}
}
}
}
}