From 0665d66323ceafa8d0b097902cfca17887c16efb Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Thu, 3 Jan 2019 10:51:19 -0700 Subject: [PATCH 1/2] Support not sending index pattern to Kuery functions --- .../src/kuery/functions/__tests__/exists.js | 11 +++++++++- .../functions/__tests__/geo_bounding_box.js | 8 +++++++ .../kuery/functions/__tests__/geo_polygon.js | 11 ++++++++++ .../src/kuery/functions/__tests__/is.js | 15 +++++++++++++ .../src/kuery/functions/__tests__/range.js | 22 +++++++++++++++++++ .../src/kuery/functions/exists.js | 3 ++- .../src/kuery/functions/geo_bounding_box.js | 2 +- .../src/kuery/functions/geo_polygon.js | 3 ++- .../kbn-es-query/src/kuery/functions/is.js | 4 ++-- .../kbn-es-query/src/kuery/functions/range.js | 2 +- 10 files changed, 74 insertions(+), 7 deletions(-) diff --git a/packages/kbn-es-query/src/kuery/functions/__tests__/exists.js b/packages/kbn-es-query/src/kuery/functions/__tests__/exists.js index 033b103bf2d11..694c044bd49ff 100644 --- a/packages/kbn-es-query/src/kuery/functions/__tests__/exists.js +++ b/packages/kbn-es-query/src/kuery/functions/__tests__/exists.js @@ -57,12 +57,21 @@ describe('kuery functions', function () { expect(_.isEqual(expected, result)).to.be(true); }); + it('should return an ES exists query without an index pattern', function () { + const expected = { + exists: { field: 'response' } + }; + + const existsNode = nodeTypes.function.buildNode('exists', 'response'); + const result = exists.toElasticsearchQuery(existsNode); + expect(_.isEqual(expected, result)).to.be(true); + }); + it('should throw an error for scripted fields', function () { const existsNode = nodeTypes.function.buildNode('exists', 'script string'); expect(exists.toElasticsearchQuery) .withArgs(existsNode, indexPattern).to.throwException(/Exists query does not support scripted fields/); }); - }); }); }); diff --git a/packages/kbn-es-query/src/kuery/functions/__tests__/geo_bounding_box.js b/packages/kbn-es-query/src/kuery/functions/__tests__/geo_bounding_box.js index d5fb98525c43d..28aee22dd94d9 100644 --- a/packages/kbn-es-query/src/kuery/functions/__tests__/geo_bounding_box.js +++ b/packages/kbn-es-query/src/kuery/functions/__tests__/geo_bounding_box.js @@ -83,6 +83,14 @@ describe('kuery functions', function () { expect(result.geo_bounding_box.geo).to.have.property('bottom_right', '50.73, -135.35'); }); + it('should return an ES geo_bounding_box query without an index pattern', function () { + const node = nodeTypes.function.buildNode('geoBoundingBox', 'geo', params); + const result = geoBoundingBox.toElasticsearchQuery(node); + expect(result).to.have.property('geo_bounding_box'); + expect(result.geo_bounding_box.geo).to.have.property('top_left', '73.12, -174.37'); + expect(result.geo_bounding_box.geo).to.have.property('bottom_right', '50.73, -135.35'); + }); + it('should use the ignore_unmapped parameter', function () { const node = nodeTypes.function.buildNode('geoBoundingBox', 'geo', params); const result = geoBoundingBox.toElasticsearchQuery(node, indexPattern); diff --git a/packages/kbn-es-query/src/kuery/functions/__tests__/geo_polygon.js b/packages/kbn-es-query/src/kuery/functions/__tests__/geo_polygon.js index 223d24e2fe116..7f01b84eef93d 100644 --- a/packages/kbn-es-query/src/kuery/functions/__tests__/geo_polygon.js +++ b/packages/kbn-es-query/src/kuery/functions/__tests__/geo_polygon.js @@ -91,6 +91,17 @@ describe('kuery functions', function () { }); }); + it('should return an ES geo_polygon query without an index pattern', function () { + const node = nodeTypes.function.buildNode('geoPolygon', 'geo', points); + const result = geoPolygon.toElasticsearchQuery(node); + expect(result).to.have.property('geo_polygon'); + expect(result.geo_polygon.geo).to.have.property('points'); + + result.geo_polygon.geo.points.forEach((point, index) => { + const expectedLatLon = `${points[index].lat}, ${points[index].lon}`; + expect(point).to.be(expectedLatLon); + }); + }); it('should use the ignore_unmapped parameter', function () { const node = nodeTypes.function.buildNode('geoPolygon', 'geo', points); diff --git a/packages/kbn-es-query/src/kuery/functions/__tests__/is.js b/packages/kbn-es-query/src/kuery/functions/__tests__/is.js index 2dca24b187875..5018b18c2e8c2 100644 --- a/packages/kbn-es-query/src/kuery/functions/__tests__/is.js +++ b/packages/kbn-es-query/src/kuery/functions/__tests__/is.js @@ -143,6 +143,21 @@ describe('kuery functions', function () { expect(result).to.eql(expected); }); + it('should return an ES match query when a concrete fieldName and value are provided without an index pattern', function () { + const expected = { + bool: { + should: [ + { match: { extension: 'jpg' } }, + ], + minimum_should_match: 1 + } + }; + + const node = nodeTypes.function.buildNode('is', 'extension', 'jpg'); + const result = is.toElasticsearchQuery(node); + expect(result).to.eql(expected); + }); + it('should support creation of phrase queries', function () { const expected = { bool: { diff --git a/packages/kbn-es-query/src/kuery/functions/__tests__/range.js b/packages/kbn-es-query/src/kuery/functions/__tests__/range.js index 25c309790f266..92108a8fb8674 100644 --- a/packages/kbn-es-query/src/kuery/functions/__tests__/range.js +++ b/packages/kbn-es-query/src/kuery/functions/__tests__/range.js @@ -86,6 +86,28 @@ describe('kuery functions', function () { expect(result).to.eql(expected); }); + it('should return an ES range query without an index pattern', function () { + const expected = { + bool: { + should: [ + { + range: { + bytes: { + gt: 1000, + lt: 8000 + } + } + } + ], + minimum_should_match: 1 + } + }; + + const node = nodeTypes.function.buildNode('range', 'bytes', { gt: 1000, lt: 8000 }); + const result = range.toElasticsearchQuery(node); + expect(result).to.eql(expected); + }); + it('should support wildcard field names', function () { const expected = { bool: { diff --git a/packages/kbn-es-query/src/kuery/functions/exists.js b/packages/kbn-es-query/src/kuery/functions/exists.js index 99570526e0166..64810fc2ba796 100644 --- a/packages/kbn-es-query/src/kuery/functions/exists.js +++ b/packages/kbn-es-query/src/kuery/functions/exists.js @@ -17,6 +17,7 @@ * under the License. */ +import { get } from 'lodash'; import * as literal from '../node_types/literal'; export function buildNodeParams(fieldName) { @@ -28,7 +29,7 @@ export function buildNodeParams(fieldName) { export function toElasticsearchQuery(node, indexPattern) { const { arguments: [ fieldNameArg ] } = node; const fieldName = literal.toElasticsearchQuery(fieldNameArg); - const field = indexPattern.fields.find(field => field.name === fieldName); + const field = get(indexPattern, 'fields', []).find(field => field.name === fieldName); if (field && field.scripted) { throw new Error(`Exists query does not support scripted fields`); diff --git a/packages/kbn-es-query/src/kuery/functions/geo_bounding_box.js b/packages/kbn-es-query/src/kuery/functions/geo_bounding_box.js index f17bf6c8e4f24..eeab146f6f698 100644 --- a/packages/kbn-es-query/src/kuery/functions/geo_bounding_box.js +++ b/packages/kbn-es-query/src/kuery/functions/geo_bounding_box.js @@ -37,7 +37,7 @@ export function buildNodeParams(fieldName, params) { export function toElasticsearchQuery(node, indexPattern) { const [ fieldNameArg, ...args ] = node.arguments; const fieldName = nodeTypes.literal.toElasticsearchQuery(fieldNameArg); - const field = indexPattern.fields.find(field => field.name === fieldName); + const field = _.get(indexPattern, 'fields', []).find(field => field.name === fieldName); const queryParams = args.reduce((acc, arg) => { const snakeArgName = _.snakeCase(arg.name); return { diff --git a/packages/kbn-es-query/src/kuery/functions/geo_polygon.js b/packages/kbn-es-query/src/kuery/functions/geo_polygon.js index 5a487eb92d40b..2e9f10071ea32 100644 --- a/packages/kbn-es-query/src/kuery/functions/geo_polygon.js +++ b/packages/kbn-es-query/src/kuery/functions/geo_polygon.js @@ -17,6 +17,7 @@ * under the License. */ +import { get } from 'lodash'; import { nodeTypes } from '../node_types'; import * as ast from '../ast'; @@ -35,7 +36,7 @@ export function buildNodeParams(fieldName, points) { export function toElasticsearchQuery(node, indexPattern) { const [ fieldNameArg, ...points ] = node.arguments; const fieldName = nodeTypes.literal.toElasticsearchQuery(fieldNameArg); - const field = indexPattern.fields.find(field => field.name === fieldName); + const field = get(indexPattern, 'fields', []).find(field => field.name === fieldName); const queryParams = { points: points.map(ast.toElasticsearchQuery) }; diff --git a/packages/kbn-es-query/src/kuery/functions/is.js b/packages/kbn-es-query/src/kuery/functions/is.js index a13d8883e495b..895b777f3eeb0 100644 --- a/packages/kbn-es-query/src/kuery/functions/is.js +++ b/packages/kbn-es-query/src/kuery/functions/is.js @@ -65,7 +65,7 @@ export function toElasticsearchQuery(node, indexPattern) { }; } - const fields = getFields(fieldNameArg, indexPattern); + const fields = indexPattern ? getFields(fieldNameArg, indexPattern) : []; // If no fields are found in the index pattern we send through the given field name as-is. We do this to preserve // the behaviour of lucene on dashboards where there are panels based on different index patterns that have different @@ -80,7 +80,7 @@ export function toElasticsearchQuery(node, indexPattern) { } const isExistsQuery = valueArg.type === 'wildcard' && value === '*'; - const isMatchAllQuery = isExistsQuery && fields && fields.length === indexPattern.fields.length; + const isMatchAllQuery = isExistsQuery && fields && indexPattern && fields.length === indexPattern.fields.length; if (isMatchAllQuery) { return { match_all: {} }; diff --git a/packages/kbn-es-query/src/kuery/functions/range.js b/packages/kbn-es-query/src/kuery/functions/range.js index 0853e53e1f81a..40c53e55c2011 100644 --- a/packages/kbn-es-query/src/kuery/functions/range.js +++ b/packages/kbn-es-query/src/kuery/functions/range.js @@ -37,7 +37,7 @@ export function buildNodeParams(fieldName, params) { export function toElasticsearchQuery(node, indexPattern) { const [ fieldNameArg, ...args ] = node.arguments; - const fields = getFields(fieldNameArg, indexPattern); + const fields = indexPattern ? getFields(fieldNameArg, indexPattern) : []; const namedArgs = extractArguments(args); const queryParams = _.mapValues(namedArgs, ast.toElasticsearchQuery); From 83b48f0a389c9855e4c50c7b770986d6ea3fb7c2 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Thu, 3 Jan 2019 11:34:06 -0700 Subject: [PATCH 2/2] fix match all inside is --- packages/kbn-es-query/src/kuery/ast/ast.js | 2 ++ packages/kbn-es-query/src/kuery/functions/is.js | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/kbn-es-query/src/kuery/ast/ast.js b/packages/kbn-es-query/src/kuery/ast/ast.js index 41fa5bc4054bf..aba5d49060466 100644 --- a/packages/kbn-es-query/src/kuery/ast/ast.js +++ b/packages/kbn-es-query/src/kuery/ast/ast.js @@ -52,6 +52,8 @@ function fromExpression(expression, parseOptions = {}, parse = parseKuery) { return parse(expression, parseOptions); } +// indexPattern isn't required, but if you pass one in, we can be more intelligent +// about how we craft the queries (e.g. scripted fields) export function toElasticsearchQuery(node, indexPattern) { if (!node || !node.type || !nodeTypes[node.type]) { return toElasticsearchQuery(nodeTypes.function.buildNode('and', [])); diff --git a/packages/kbn-es-query/src/kuery/functions/is.js b/packages/kbn-es-query/src/kuery/functions/is.js index 895b777f3eeb0..27e64d23c1542 100644 --- a/packages/kbn-es-query/src/kuery/functions/is.js +++ b/packages/kbn-es-query/src/kuery/functions/is.js @@ -44,6 +44,7 @@ export function buildNodeParams(fieldName, value, isPhrase = false) { export function toElasticsearchQuery(node, indexPattern) { const { arguments: [ fieldNameArg, valueArg, isPhraseArg ] } = node; + const fieldName = ast.toElasticsearchQuery(fieldNameArg); const value = !_.isUndefined(valueArg) ? ast.toElasticsearchQuery(valueArg) : valueArg; const type = isPhraseArg.value ? 'phrase' : 'best_fields'; @@ -80,7 +81,10 @@ export function toElasticsearchQuery(node, indexPattern) { } const isExistsQuery = valueArg.type === 'wildcard' && value === '*'; - const isMatchAllQuery = isExistsQuery && fields && indexPattern && fields.length === indexPattern.fields.length; + const isAllFieldsQuery = + (fieldNameArg.type === 'wildcard' && fieldName === '*') + || (fields && indexPattern && fields.length === indexPattern.fields.length); + const isMatchAllQuery = isExistsQuery && isAllFieldsQuery; if (isMatchAllQuery) { return { match_all: {} };