Skip to content

Commit

Permalink
Better support for string values in search queries (#1189)
Browse files Browse the repository at this point in the history
* Allow searchbar string values to begin with numbers; allow non-string types to be passed to string fields

* changelog
  • Loading branch information
chandlerprall authored Sep 13, 2018
1 parent 0836392 commit b02c8e4
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
**Bug fixes**

- Fixed an issue in `EuiTooltip` because IE1 didn't support `document.contains()` ([#1190](https://github.com/elastic/eui/pull/1190))
- Fixed some issues around parsing string values in EuiSearchBar / EuiQuery ([#1189](https://github.com/elastic/eui/pull/1189))

## [`4.0.0`](https://github.com/elastic/eui/tree/v4.0.0)

Expand Down
21 changes: 16 additions & 5 deletions src/components/search_bar/query/default_syntax.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,11 @@ containsOrValues
)* space? ")" { return [ head, ...tail ]; }
rangeValue
= number
= numberWord
/ date
containsValue
= number
= numberWord
/ date
/ booleanWord
/ word
Expand Down Expand Up @@ -152,6 +152,11 @@ boolean
number
= [\\-]?[0-9]+("."[0-9]+)* { return Exp.number(text(), location()); }
// only match numbers followed by whitespace or end of input
numberWord
= num:number &space { return num; }
/ num:number !. { return num; }
date
= "'" expression:((!"'" .)+ { return text(); }) "'" {
return Exp.date(expression, location());
Expand Down Expand Up @@ -210,14 +215,20 @@ const resolveFieldValue = (field, valueExpression, ctx) => {
if (isArray(valueExpression)) {
return valueExpression.map(exp => resolveFieldValue(field, exp, ctx));
}
const { type, expression, location } = valueExpression;
const { location } = valueExpression;
let { type, expression } = valueExpression;
if (schema && !schema.fields[field] && schema.strict) {
error(`Unknown field \`${field}\``, location);
}
const schemaField = schema && schema.fields[field];
if (schemaField && schemaField.type !== type && schema.strict) {
const valueDesc = schemaField.valueDescription || `a ${schemaField.type} value`;
error(`Expected ${valueDesc} for field \`${field}\`, but found \`${expression}\``, location);
if (schemaField.type === 'string') {
expression = valueExpression.expression = expression.toString();
type = valueExpression.type = 'string';
} else {
const valueDesc = schemaField.valueDescription || `a ${schemaField.type} value`;
error(`Expected ${valueDesc} for field \`${field}\`, but found \`${expression}\``, location);
}
}
switch(type) {

Expand Down
52 changes: 52 additions & 0 deletions src/components/search_bar/query/default_syntax.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,36 @@ describe('defaultSyntax', () => {
expect(printedQuery).toBe(query);
});

test('number type', () => {
const query = 'count:15';
const ast = defaultSyntax.parse(query);

expect(ast).toBeDefined();
expect(ast.clauses).toHaveLength(1);

const clause = ast.getSimpleFieldClause('count');
expect(clause).toBeDefined();
expect(AST.Field.isInstance(clause)).toBe(true);
expect(AST.Match.isMustClause(clause)).toBe(true);
expect(clause.field).toBe('count');
expect(clause.value).toBe(15);
});

test('string that starts with a number', () => {
const query = 'count:15n';
const ast = defaultSyntax.parse(query);

expect(ast).toBeDefined();
expect(ast.clauses).toHaveLength(1);

const clause = ast.getSimpleFieldClause('count');
expect(clause).toBeDefined();
expect(AST.Field.isInstance(clause)).toBe(true);
expect(AST.Match.isMustClause(clause)).toBe(true);
expect(clause.field).toBe('count');
expect(clause.value).toBe('15n');
});

test('strict schema - flags - listed', () => {

const query = `is:active`;
Expand Down Expand Up @@ -933,4 +963,26 @@ describe('defaultSyntax', () => {
}).toThrow('Unknown field `name`');
});

test('strict schema - string fields have their values coerced', () => {
const query = `name:15`;
const schema = {
strict: true,
fields: {
name: {
type: 'string'
}
}
};
const ast = defaultSyntax.parse(query, { schema });

expect(ast).toBeDefined();
expect(ast.clauses).toHaveLength(1);

const clause = ast.getSimpleFieldClause('name');
expect(clause).toBeDefined();
expect(AST.Field.isInstance(clause)).toBe(true);
expect(AST.Match.isMustClause(clause)).toBe(true);
expect(clause.field).toBe('name');
expect(clause.value).toBe('15');
});
});

0 comments on commit b02c8e4

Please sign in to comment.