Merge pull request #3244 from omnivore-app/improve-advanced-search

improve advanced search
This commit is contained in:
Hongbo Wu 2023-12-12 19:53:29 +08:00 committed by GitHub
commit 528163905d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 149 additions and 287 deletions

View file

@ -1,4 +1,4 @@
import { LiqeQuery } from '@omnivore/liqe'
import { ExpressionToken, LiqeQuery } from '@omnivore/liqe'
import { DateTime } from 'luxon'
import { DeepPartial, ObjectLiteral } from 'typeorm'
import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity'
@ -130,7 +130,8 @@ export const sortParamsToSort = (
}
const getColumnName = (field: string) => {
switch (field) {
const lowerCaseField = field.toLowerCase()
switch (lowerCaseField) {
case 'language':
return 'item_language'
case 'subscription':
@ -138,17 +139,17 @@ const getColumnName = (field: string) => {
return 'subscription'
case 'site':
return 'site_name'
case 'wordsCount':
case 'wordscount':
return 'word_count'
case 'readPosition':
case 'readposition':
return 'reading_progress_bottom_percent'
case 'saved':
case 'read':
case 'updated':
case 'published':
return `${field}_at`
return `${lowerCaseField}_at`
default:
return field
return lowerCaseField
}
}
@ -167,50 +168,58 @@ export const buildQuery = (
return query
}
const serializeImplicitField = (
expression: ExpressionToken
): string | null => {
if (expression.type !== 'LiteralExpression') {
throw new Error('Expected a literal expression')
}
const value = expression.value?.toString()
if (value === undefined || value === '') {
return null
}
const param = `implicit_field_${parameters.length}`
const alias = `rank_${parameters.length}`
selects.push({
column: `ts_rank_cd(library_item.search_tsv, websearch_to_tsquery('english', :${param}))`,
alias,
})
orders.push({ by: alias, order: SortOrder.DESCENDING })
return escapeQueryWithParameters(
`websearch_to_tsquery('english', :${param}) @@ library_item.search_tsv`,
{ [param]: value }
)
}
const serializeTagExpression = (ast: LiqeQuery): string | null => {
if (ast.type !== 'Tag') {
throw new Error('Expected a tag expression.')
throw new Error('Expected a tag expression')
}
const { field, expression } = ast
if (field.type === 'ImplicitField') {
return serializeImplicitField(expression)
} else {
if (expression.type !== 'LiteralExpression') {
throw new Error('Expected a literal expression.')
}
const value = expression.value?.toString()
if (value === undefined || value === '') {
// ignore empty values
return null
}
const param = `implicit_field_${parameters.length}`
const alias = `rank_${parameters.length}`
selects.push({
column: `ts_rank_cd(library_item.search_tsv, websearch_to_tsquery('english', :${param}))`,
alias,
})
const value = expression.value?.toString()
if (!value) {
// ignore empty values
return null
}
orders.push({ by: alias, order: SortOrder.DESCENDING })
return escapeQueryWithParameters(
`websearch_to_tsquery('english', :${param}) @@ library_item.search_tsv`,
{ [param]: value }
)
} else {
switch (field.name) {
switch (field.name.toLowerCase()) {
case 'in': {
if (expression.type !== 'LiteralExpression') {
throw new Error('Expected a literal expression.')
}
const folder = expression.value?.toString()
if (!folder) {
throw new Error('Expected a value.')
}
switch (folder) {
switch (value.toLowerCase()) {
case InFilter.ALL:
return null
case InFilter.ARCHIVE:
@ -224,7 +233,7 @@ export const buildQuery = (
const param = `folder_${parameters.length}`
const folderSql = escapeQueryWithParameters(
`library_item.folder = :${param}`,
{ [param]: folder }
{ [param]: value }
)
sql = `(${sql} AND ${folderSql})`
}
@ -235,16 +244,7 @@ export const buildQuery = (
}
case 'is': {
if (expression.type !== 'LiteralExpression') {
throw new Error('Expected a literal expression.')
}
const value = expression.value?.toString()
if (!value) {
throw new Error('Expected a value.')
}
switch (value) {
switch (value.toLowerCase()) {
case ReadFilter.READ:
return 'library_item.reading_progress_bottom_percent > 98'
case ReadFilter.READING:
@ -256,15 +256,6 @@ export const buildQuery = (
}
}
case 'type': {
if (expression.type !== 'LiteralExpression') {
throw new Error('Expected a literal expression.')
}
const value = expression.value?.toString()
if (!value) {
throw new Error('Expected a value.')
}
const param = `type_${parameters.length}`
return escapeQueryWithParameters(
@ -275,16 +266,7 @@ export const buildQuery = (
)
}
case 'label': {
if (expression.type !== 'LiteralExpression') {
throw new Error('Expected a literal expression.')
}
const value = expression.value?.toString()?.toLowerCase()
if (!value) {
throw new Error('Expected a value.')
}
const labels = value.split(',')
const labels = value.toLowerCase().split(',')
return (
labels
.map((label) => {
@ -313,15 +295,6 @@ export const buildQuery = (
)
}
case 'sort': {
if (expression.type !== 'LiteralExpression') {
throw new Error('Expected a literal expression.')
}
const value = expression.value?.toString()
if (!value) {
throw new Error('Expected a value.')
}
const [sort, sortOrder] = value.split('-')
if (sort.toLowerCase() === 'score') {
// score is not a column and is handled separately
@ -329,7 +302,7 @@ export const buildQuery = (
}
const order =
sortOrder?.toUpperCase() === 'ASC'
sortOrder?.toLowerCase() === 'asc'
? SortOrder.ASCENDING
: SortOrder.DESCENDING
@ -338,16 +311,7 @@ export const buildQuery = (
return null
}
case 'has': {
if (expression.type !== 'LiteralExpression') {
throw new Error('Expected a literal expression.')
}
const value = expression.value?.toString()
if (!value) {
throw new Error('Expected a value.')
}
switch (value) {
switch (value.toLowerCase()) {
case HasFilter.HIGHLIGHTS:
return "library_item.highlight_annotations <> '{}'"
case HasFilter.LABELS:
@ -362,19 +326,10 @@ export const buildQuery = (
case 'read':
case 'updated':
case 'published': {
if (expression.type !== 'LiteralExpression') {
throw new Error('Expected a literal expression.')
}
const date = expression.value?.toString()
if (!date) {
throw new Error('Expected a value.')
}
let startDate: Date | undefined
let endDate: Date | undefined
// check for special date filters
switch (date.toLowerCase()) {
switch (value.toLowerCase()) {
case 'today':
startDate = DateTime.local().startOf('day').toJSDate()
break
@ -392,19 +347,19 @@ export const buildQuery = (
break
default: {
// check for date ranges
const [start, end] = date.split('..')
const [start, end] = value.split('..')
// validate date
if (start && start !== '*') {
startDate = new Date(start)
if (isNaN(startDate.getTime())) {
throw new Error('Invalid start date.')
throw new Error('Invalid start date')
}
}
if (end && end !== '*') {
endDate = new Date(end)
if (isNaN(endDate.getTime())) {
throw new Error('Invalid end date.')
throw new Error('Invalid end date')
}
}
}
@ -425,15 +380,6 @@ export const buildQuery = (
case 'subscription':
case 'rss':
case 'language': {
if (expression.type !== 'LiteralExpression') {
throw new Error('Expected a literal expression.')
}
const value = expression.value?.toString()
if (!value) {
throw new Error('Expected a value.')
}
const columnName = getColumnName(field.name)
const param = `term_${field.name}_${parameters.length}`
@ -450,16 +396,6 @@ export const buildQuery = (
case 'description':
case 'note':
case 'site': {
if (expression.type !== 'LiteralExpression') {
throw new Error('Expected a literal expression.')
}
// normalize the term to lower case
const value = expression.value?.toString()?.toLowerCase()
if (!value) {
throw new Error('Expected a value.')
}
const columnName = getColumnName(field.name)
const param = `match_${field.name}_${parameters.length}`
const wildcardParam = `match_${field.name}_wildcard_${parameters.length}`
@ -473,13 +409,9 @@ export const buildQuery = (
)
}
case 'includes': {
if (expression.type !== 'LiteralExpression') {
throw new Error('Expected a literal expression.')
}
const ids = expression.value?.toString()?.split(',')
const ids = value.split(',')
if (!ids || ids.length === 0) {
throw new Error('Expected a value.')
throw new Error('Expected ids')
}
const param = `includes_${parameters.length}`
@ -488,16 +420,7 @@ export const buildQuery = (
[param]: ids,
})
}
case 'recommendedBy': {
if (expression.type !== 'LiteralExpression') {
throw new Error('Expected a literal expression.')
}
const value = expression.value?.toString()
if (!value) {
throw new Error('Expected a value.')
}
case 'recommendedby': {
const param = `recommendedBy_${parameters.length}`
if (value === '*') {
// select all if * is provided
@ -512,17 +435,8 @@ export const buildQuery = (
)
}
case 'no': {
if (expression.type !== 'LiteralExpression') {
throw new Error('Expected a literal expression.')
}
const value = expression.value?.toString()
if (!value) {
throw new Error('Expected a value.')
}
let column = ''
switch (value) {
switch (value.toLowerCase()) {
case 'highlight':
column = 'highlight_annotations'
break
@ -543,41 +457,33 @@ export const buildQuery = (
case 'event':
// mode is ignored and used only by the frontend
return null
case 'readPosition':
case 'wordsCount': {
if (expression.type !== 'LiteralExpression') {
throw new Error('Expected a literal expression.')
}
let value = expression.value?.toString()
if (!value) {
throw new Error('Expected a value.')
}
case 'readposition':
case 'wordscount': {
const column = getColumnName(field.name)
const operatorRegex = /([<>]=?)/
const operator = value.match(operatorRegex)?.[0]
if (!operator) {
throw new Error('Expected a value.')
throw new Error('Expected operator')
}
value = value.replace(operatorRegex, '')
if (!value) {
throw new Error('Expected a value.')
}
const newValue = value.replace(operatorRegex, '')
const param = `range_${field.name}_${parameters.length}`
return escapeQueryWithParameters(
`library_item.${column} ${operator} :${param}`,
{
[param]: parseInt(value, 10),
[param]: parseInt(newValue, 10),
}
)
}
default:
throw new Error(`Unexpected keyword: ${field.name}`)
// treat unknown fields as implicit fields
return serializeImplicitField({
...expression,
value: `${field.name}:${value}`,
})
}
}
}
@ -594,7 +500,7 @@ export const buildQuery = (
} else if (ast.operator.operator === 'OR') {
operator = 'OR'
} else {
throw new Error('Unexpected operator.')
throw new Error('Unexpected operator')
}
const left = serialize(ast.left)
@ -635,7 +541,7 @@ export const buildQuery = (
return `(${serialized})`
}
throw new Error('Missing AST type.')
return null
}
return serialize(searchQuery)

View file

@ -8,14 +8,14 @@ __ -> whitespace_character:+ {% (data) => data[0].length %}
whitespace_character -> [ \t\n\v\f] {% id %}
# Numbers
decimal -> "-":? [0-9]:+ ("." [0-9]:+):? {%
(data) => parseFloat(
(data[0] || "") +
data[1].join("") +
(data[2] ? "."+data[2][1].join("") : "")
)
%}
# # Numbers
# decimal -> "-":? [0-9]:+ ("." [0-9]:+):? {%
# (data) => parseFloat(
# (data[0] || "") +
# data[1].join("") +
# (data[2] ? "."+data[2][1].join("") : "")
# )
# %}
# Double-quoted string
dqstring -> "\"" dstrchar:* "\"" {% (data) => data[1].join('') %}
@ -198,9 +198,9 @@ field ->
| dqstring {% (data, start) => ({type: 'LiteralExpression', name: data[0], quoted: true, quotes: 'double', location: {start, end: start + data[0].length + 2}}) %}
expression ->
decimal {% (data, start) => ({type: 'Tag', expression: {location: {start, end: start + data.join('').length}, type: 'LiteralExpression', quoted: false, value: Number(data.join(''))}}) %}
| regex {% (data, start) => ({type: 'Tag', expression: {location: {start, end: start + data.join('').length}, type: 'RegexExpression', value: data.join('')}}) %}
| range {% (data) => data[0] %}
# decimal {% (data, start) => ({type: 'Tag', expression: {location: {start, end: start + data.join('').length}, type: 'LiteralExpression', quoted: false, value: Number(data.join(''))}}) %}
regex {% (data, start) => ({type: 'Tag', expression: {location: {start, end: start + data.join('').length}, type: 'RegexExpression', value: data.join('')}}) %}
# | range {% (data) => data[0] %}
| unquoted_value {% (data, start, reject) => {
const value = data.join('');
@ -236,36 +236,36 @@ expression ->
| sqstring {% (data, start) => ({type: 'Tag', expression: {location: {start, end: start + data.join('').length + 2}, type: 'LiteralExpression', quoted: true, quotes: 'single', value: data.join('')}}) %}
| dqstring {% (data, start) => ({type: 'Tag', expression: {location: {start, end: start + data.join('').length + 2}, type: 'LiteralExpression', quoted: true, quotes: 'double', value: data.join('')}}) %}
range ->
range_open decimal " TO " decimal range_close {% (data, start) => {
return {
location: {
start,
},
type: 'Tag',
expression: {
location: {
start: data[0].location.start,
end: data[4].location.start + 1,
},
type: 'RangeExpression',
range: {
min: data[1],
minInclusive: data[0].inclusive,
maxInclusive: data[4].inclusive,
max: data[3],
}
}
}
} %}
range_open ->
"[" {% (data, start) => ({location: {start}, inclusive: true}) %}
| "{" {% (data, start) => ({location: {start}, inclusive: false}) %}
range_close ->
"]" {% (data, start) => ({location: {start}, inclusive: true}) %}
| "}" {% (data, start) => ({location: {start}, inclusive: false}) %}
# range ->
# range_open decimal " TO " decimal range_close {% (data, start) => {
# return {
# location: {
# start,
# },
# type: 'Tag',
# expression: {
# location: {
# start: data[0].location.start,
# end: data[4].location.start + 1,
# },
# type: 'RangeExpression',
# range: {
# min: data[1],
# minInclusive: data[0].inclusive,
# maxInclusive: data[4].inclusive,
# max: data[3],
# }
# }
# }
# } %}
#
# range_open ->
# "[" {% (data, start) => ({location: {start}, inclusive: true}) %}
# | "{" {% (data, start) => ({location: {start}, inclusive: false}) %}
#
# range_close ->
# "]" {% (data, start) => ({location: {start}, inclusive: true}) %}
# | "}" {% (data, start) => ({location: {start}, inclusive: false}) %}
comparison_operator ->
(
@ -292,4 +292,4 @@ regex_flags ->
[gmiyusd]:+ {% d => d[0].join('') %}
unquoted_value ->
[a-zA-Z_*?@#$\u0080-\uFFFF] [a-zA-Z\.\-_*?@#$\u0080-\uFFFF]:* {% d => d[0] + d[1].join('') %}
[a-zA-Z_*?@#$\u0080-\uFFFF0-9] [a-zA-Z\.\-_*?@#$\u0080-\uFFFF0-9]:* {% d => d[0] + d[1].join('') %}

View file

@ -42,22 +42,6 @@ const grammar: Grammar = {
{"name": "__$ebnf$1", "symbols": ["__$ebnf$1", "whitespace_character"], "postprocess": (d) => d[0].concat([d[1]])},
{"name": "__", "symbols": ["__$ebnf$1"], "postprocess": (data) => data[0].length},
{"name": "whitespace_character", "symbols": [/[ \t\n\v\f]/], "postprocess": id},
{"name": "decimal$ebnf$1", "symbols": [{"literal":"-"}], "postprocess": id},
{"name": "decimal$ebnf$1", "symbols": [], "postprocess": () => null},
{"name": "decimal$ebnf$2", "symbols": [/[0-9]/]},
{"name": "decimal$ebnf$2", "symbols": ["decimal$ebnf$2", /[0-9]/], "postprocess": (d) => d[0].concat([d[1]])},
{"name": "decimal$ebnf$3$subexpression$1$ebnf$1", "symbols": [/[0-9]/]},
{"name": "decimal$ebnf$3$subexpression$1$ebnf$1", "symbols": ["decimal$ebnf$3$subexpression$1$ebnf$1", /[0-9]/], "postprocess": (d) => d[0].concat([d[1]])},
{"name": "decimal$ebnf$3$subexpression$1", "symbols": [{"literal":"."}, "decimal$ebnf$3$subexpression$1$ebnf$1"]},
{"name": "decimal$ebnf$3", "symbols": ["decimal$ebnf$3$subexpression$1"], "postprocess": id},
{"name": "decimal$ebnf$3", "symbols": [], "postprocess": () => null},
{"name": "decimal", "symbols": ["decimal$ebnf$1", "decimal$ebnf$2", "decimal$ebnf$3"], "postprocess":
(data) => parseFloat(
(data[0] || "") +
data[1].join("") +
(data[2] ? "."+data[2][1].join("") : "")
)
},
{"name": "dqstring$ebnf$1", "symbols": []},
{"name": "dqstring$ebnf$1", "symbols": ["dqstring$ebnf$1", "dstrchar"], "postprocess": (d) => d[0].concat([d[1]])},
{"name": "dqstring", "symbols": [{"literal":"\""}, "dqstring$ebnf$1", {"literal":"\""}], "postprocess": (data) => data[1].join('')},
@ -213,9 +197,7 @@ const grammar: Grammar = {
{"name": "field", "symbols": [/[_a-zA-Z$]/, "field$ebnf$1"], "postprocess": (data, start) => ({type: 'LiteralExpression', name: data[0] + data[1].join(''), quoted: false, location: {start, end: start + (data[0] + data[1].join('')).length}})},
{"name": "field", "symbols": ["sqstring"], "postprocess": (data, start) => ({type: 'LiteralExpression', name: data[0], quoted: true, quotes: 'single', location: {start, end: start + data[0].length + 2}})},
{"name": "field", "symbols": ["dqstring"], "postprocess": (data, start) => ({type: 'LiteralExpression', name: data[0], quoted: true, quotes: 'double', location: {start, end: start + data[0].length + 2}})},
{"name": "expression", "symbols": ["decimal"], "postprocess": (data, start) => ({type: 'Tag', expression: {location: {start, end: start + data.join('').length}, type: 'LiteralExpression', quoted: false, value: Number(data.join(''))}})},
{"name": "expression", "symbols": ["regex"], "postprocess": (data, start) => ({type: 'Tag', expression: {location: {start, end: start + data.join('').length}, type: 'RegexExpression', value: data.join('')}})},
{"name": "expression", "symbols": ["range"], "postprocess": (data) => data[0]},
{"name": "expression", "symbols": ["unquoted_value"], "postprocess": (data, start, reject) => {
const value = data.join('');
@ -250,32 +232,6 @@ const grammar: Grammar = {
} },
{"name": "expression", "symbols": ["sqstring"], "postprocess": (data, start) => ({type: 'Tag', expression: {location: {start, end: start + data.join('').length + 2}, type: 'LiteralExpression', quoted: true, quotes: 'single', value: data.join('')}})},
{"name": "expression", "symbols": ["dqstring"], "postprocess": (data, start) => ({type: 'Tag', expression: {location: {start, end: start + data.join('').length + 2}, type: 'LiteralExpression', quoted: true, quotes: 'double', value: data.join('')}})},
{"name": "range$string$1", "symbols": [{"literal":" "}, {"literal":"T"}, {"literal":"O"}, {"literal":" "}], "postprocess": (d) => d.join('')},
{"name": "range", "symbols": ["range_open", "decimal", "range$string$1", "decimal", "range_close"], "postprocess": (data, start) => {
return {
location: {
start,
},
type: 'Tag',
expression: {
location: {
start: data[0].location.start,
end: data[4].location.start + 1,
},
type: 'RangeExpression',
range: {
min: data[1],
minInclusive: data[0].inclusive,
maxInclusive: data[4].inclusive,
max: data[3],
}
}
}
} },
{"name": "range_open", "symbols": [{"literal":"["}], "postprocess": (data, start) => ({location: {start}, inclusive: true})},
{"name": "range_open", "symbols": [{"literal":"{"}], "postprocess": (data, start) => ({location: {start}, inclusive: false})},
{"name": "range_close", "symbols": [{"literal":"]"}], "postprocess": (data, start) => ({location: {start}, inclusive: true})},
{"name": "range_close", "symbols": [{"literal":"}"}], "postprocess": (data, start) => ({location: {start}, inclusive: false})},
{"name": "comparison_operator$subexpression$1", "symbols": [{"literal":":"}]},
{"name": "comparison_operator$subexpression$1$string$1", "symbols": [{"literal":":"}, {"literal":"="}], "postprocess": (d) => d.join('')},
{"name": "comparison_operator$subexpression$1", "symbols": ["comparison_operator$subexpression$1$string$1"]},
@ -299,8 +255,8 @@ const grammar: Grammar = {
{"name": "regex_flags$ebnf$1", "symbols": ["regex_flags$ebnf$1", /[gmiyusd]/], "postprocess": (d) => d[0].concat([d[1]])},
{"name": "regex_flags", "symbols": ["regex_flags$ebnf$1"], "postprocess": d => d[0].join('')},
{"name": "unquoted_value$ebnf$1", "symbols": []},
{"name": "unquoted_value$ebnf$1", "symbols": ["unquoted_value$ebnf$1", /[a-zA-Z\.\-_*?@#$\u0080-\uFFFF]/], "postprocess": (d) => d[0].concat([d[1]])},
{"name": "unquoted_value", "symbols": [/[a-zA-Z_*?@#$\u0080-\uFFFF]/, "unquoted_value$ebnf$1"], "postprocess": d => d[0] + d[1].join('')}
{"name": "unquoted_value$ebnf$1", "symbols": ["unquoted_value$ebnf$1", /[a-zA-Z\.\-_*?@#$\u0080-\uFFFF0-9]/], "postprocess": (d) => d[0].concat([d[1]])},
{"name": "unquoted_value", "symbols": [/[a-zA-Z_*?@#$\u0080-\uFFFF0-9]/, "unquoted_value$ebnf$1"], "postprocess": d => d[0] + d[1].join('')}
],
ParserStart: "main",
};

View file

@ -93,12 +93,12 @@ test('name:/(david)|(john)/', testQuery, ['david', 'john']);
test('name:/(David)|(John)/', testQuery, []);
test('name:/(David)|(John)/i', testQuery, ['david', 'john']);
test('height:[200 TO 300]', testQuery, ['robert', 'noah']);
test('height:[220 TO 300]', testQuery, ['robert', 'noah']);
test('height:{220 TO 300]', testQuery, ['noah']);
test('height:[200 TO 225]', testQuery, ['robert', 'noah']);
test('height:[200 TO 225}', testQuery, ['robert']);
test('height:{220 TO 225}', testQuery, []);
test.skip('height:[200 TO 300]', testQuery, ['robert', 'noah']);
test.skip('height:[220 TO 300]', testQuery, ['robert', 'noah']);
test.skip('height:{220 TO 300]', testQuery, ['noah']);
test.skip('height:[200 TO 225]', testQuery, ['robert', 'noah']);
test.skip('height:[200 TO 225}', testQuery, ['robert']);
test.skip('height:{220 TO 225}', testQuery, []);
test('NOT David', testQuery, ['john', 'mike', 'robert', 'noah', 'foo bar', 'fox']);
test('-David', testQuery, ['john', 'mike', 'robert', 'noah', 'foo bar', 'fox']);
@ -115,12 +115,12 @@ test('name:David OR name:John', testQuery, ['david', 'john']);
test('name:"david" OR name:"john"', testQuery, ['david', 'john']);
test('name:"David" OR name:"John"', testQuery, []);
test('height:=175', testQuery, ['john', 'mike']);
test('height:>200', testQuery, ['robert', 'noah']);
test('height:>220', testQuery, ['noah']);
test('height:>=220', testQuery, ['robert', 'noah']);
test.skip('height:=175', testQuery, ['john', 'mike']);
test.skip('height:>200', testQuery, ['robert', 'noah']);
test.skip('height:>220', testQuery, ['noah']);
test.skip('height:>=220', testQuery, ['robert', 'noah']);
test('height:=175 AND NOT name:mike', testQuery, ['john']);
test.skip('height:=175 AND NOT name:mike', testQuery, ['john']);
test('"member"', testQuery, ['robert']);
@ -138,9 +138,9 @@ test('subscribed:true', testQuery, ['noah']);
test('email:/[^.:@\\s](?:[^:@\\s]*[^.:@\\s])?@[^.@\\s]+(?:\\.[^.@\\s]+)*/', testQuery, ['noah']);
test('phoneNumber:"404-050-2611"', testQuery, ['noah']);
test('phoneNumber:404', testQuery, ['noah']);
test.skip('phoneNumber:404', testQuery, ['noah']);
test('balance:364', testQuery, ['noah']);
test.skip('balance:364', testQuery, ['noah']);
test('(David)', testQuery, ['david']);
test('(name:david OR name:john)', testQuery, ['david', 'john']);

View file

@ -83,7 +83,7 @@ test(
],
);
test(
test.skip(
'matches or',
testQuery,
'name:foo OR name:bar OR height:=180',
@ -181,7 +181,7 @@ test.skip(
],
);
test(
test.skip(
'matches number',
testQuery,
'height:=180',
@ -195,7 +195,7 @@ test(
],
);
test(
test.skip(
'matches range',
testQuery,
'height:[100 TO 200]',

View file

@ -529,7 +529,7 @@ test.skip('foo: bar', testQuery, {
type: 'Tag',
});
test('foo:123', testQuery, {
test.skip('foo:123', testQuery, {
expression: {
location: {
end: 7,
@ -564,7 +564,7 @@ test('foo:123', testQuery, {
type: 'Tag',
});
test('foo:=123', testQuery, {
test.skip('foo:=123', testQuery, {
expression: {
location: {
end: 8,
@ -636,7 +636,7 @@ test.skip('foo:= 123', testQuery, {
type: 'Tag',
});
test('foo:=-123', testQuery, {
test.skip('foo:=-123', testQuery, {
expression: {
location: {
end: 9,
@ -671,7 +671,7 @@ test('foo:=-123', testQuery, {
type: 'Tag',
});
test('foo:=123.4', testQuery, {
test.skip('foo:=123.4', testQuery, {
expression: {
location: {
end: 10,
@ -706,7 +706,7 @@ test('foo:=123.4', testQuery, {
type: 'Tag',
});
test('foo:>=123', testQuery, {
test.skip('foo:>=123', testQuery, {
expression: {
location: {
end: 9,
@ -2415,7 +2415,7 @@ test('(foo:bar OR baz:qux) OR quuz:corge', testQuery, {
type: 'LogicalExpression',
});
test('[1 TO 2]', testQuery, {
test.skip('[1 TO 2]', testQuery, {
expression: {
location: {
end: 8,
@ -2438,7 +2438,7 @@ test('[1 TO 2]', testQuery, {
type: 'Tag',
});
test('{1 TO 2]', testQuery, {
test.skip('{1 TO 2]', testQuery, {
expression: {
location: {
end: 8,
@ -2461,7 +2461,7 @@ test('{1 TO 2]', testQuery, {
type: 'Tag',
});
test('[1 TO 2}', testQuery, {
test.skip('[1 TO 2}', testQuery, {
expression: {
location: {
end: 8,
@ -2484,7 +2484,7 @@ test('[1 TO 2}', testQuery, {
type: 'Tag',
});
test('{1 TO 2}', testQuery, {
test.skip('{1 TO 2}', testQuery, {
expression: {
location: {
end: 8,

View file

@ -52,19 +52,19 @@ test('foo:bar', testQuery);
// https://github.com/gajus/liqe/issues/19
test.skip('foo: bar', testQuery);
test('foo:123', testQuery);
test.skip('foo:123', testQuery);
test('foo:=123', testQuery);
test.skip('foo:=123', testQuery);
// https://github.com/gajus/liqe/issues/18
// https://github.com/gajus/liqe/issues/19
test.skip('foo:= 123', testQuery);
test('foo:=-123', testQuery);
test.skip('foo:=-123', testQuery);
test('foo:=123.4', testQuery);
test.skip('foo:=123.4', testQuery);
test('foo:>=123', testQuery);
test.skip('foo:>=123', testQuery);
test('foo:true', testQuery);
@ -124,10 +124,10 @@ test('(foo:bar OR (baz:qux OR quuz:corge))', testQuery);
test('((foo:bar OR baz:qux) OR quuz:corge)', testQuery);
test('[1 TO 2]', testQuery);
test.skip('[1 TO 2]', testQuery);
test('{1 TO 2]', testQuery);
test.skip('{1 TO 2]', testQuery);
test('[1 TO 2}', testQuery);
test.skip('[1 TO 2}', testQuery);
test('{1 TO 2}', testQuery);
test.skip('{1 TO 2}', testQuery);