03f977246f
* Bump Version * updated * Bump patch version * Optimization should only occur on single values * Wildcard semantically equivalent to query_string* * Add unit test for optimization * Move code-checks to yml * Add tests path to code-checks * Add lib path for code-checks * Install deps from local * Update DSL optimization unit test --------- Co-authored-by: Terrance DeJesus <99630311+terrancedejesus@users.noreply.github.com>
143 lines
5.0 KiB
Python
143 lines
5.0 KiB
Python
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
# or more contributor license agreements. Licensed under the Elastic License
|
|
# 2.0; you may not use this file except in compliance with the Elastic License
|
|
# 2.0.
|
|
|
|
import unittest
|
|
|
|
import kql
|
|
|
|
|
|
class TestKQLtoDSL(unittest.TestCase):
|
|
def validate(self, kql_source, dsl, **kwargs):
|
|
actual_dsl = kql.to_dsl(kql_source, **kwargs)
|
|
self.assertListEqual(list(actual_dsl), ["bool"])
|
|
self.assertDictEqual(actual_dsl["bool"], dsl)
|
|
|
|
def test_field_match(self):
|
|
def match(**kv):
|
|
return {"filter": [{"match": kv}]}
|
|
|
|
self.validate("user:bob", match(user="bob"))
|
|
self.validate("number:-1", match(number=-1))
|
|
self.validate("number:1.1", match(number=1.1))
|
|
self.validate("boolean:true", match(boolean=True))
|
|
self.validate("boolean:false", match(boolean=False))
|
|
|
|
def test_field_exists(self):
|
|
self.validate("user:*", {"filter": [{"exists": {"field": "user"}}]})
|
|
|
|
def test_field_inequality(self):
|
|
def rng(op, val):
|
|
return {"filter": [{"range": {"field": {op: val}}}]}
|
|
|
|
self.validate("field < value", rng("lt", "value"))
|
|
self.validate("field > -1", rng("gt", -1))
|
|
self.validate("field <= 1.1", rng("lte", 1.1))
|
|
self.validate("field >= 0", rng("gte", 0))
|
|
self.validate("field >= abc", rng("gte", "abc"))
|
|
|
|
def test_or_query(self):
|
|
self.validate(
|
|
"field:value or field2:value2",
|
|
{"should": [{"match": {"field": "value"}}, {"match": {"field2": "value2"}}], "minimum_should_match": 1},
|
|
)
|
|
|
|
def test_and_query(self):
|
|
self.validate(
|
|
"field:value and field2:value2",
|
|
{"filter": [{"match": {"field": "value"}}, {"match": {"field2": "value2"}}]},
|
|
)
|
|
|
|
def test_not_query(self):
|
|
self.validate("not field:value", {"must_not": [{"match": {"field": "value"}}]})
|
|
self.validate("field:(not value)", {"must_not": [{"match": {"field": "value"}}]})
|
|
self.validate(
|
|
"field:(a and not b)", {"filter": [{"match": {"field": "a"}}], "must_not": [{"match": {"field": "b"}}]}
|
|
)
|
|
self.validate(
|
|
"not field:value and not field2:value2",
|
|
{"must_not": [{"match": {"field": "value"}}, {"match": {"field2": "value2"}}]},
|
|
)
|
|
self.validate(
|
|
"not (field:value or field2:value2)",
|
|
{
|
|
"must_not": [
|
|
{
|
|
"bool": {
|
|
"minimum_should_match": 1,
|
|
"should": [{"match": {"field": "value"}}, {"match": {"field2": "value2"}}],
|
|
}
|
|
}
|
|
]
|
|
},
|
|
optimize=False,
|
|
)
|
|
|
|
self.validate(
|
|
"not (field:value and field2:value2)",
|
|
{"must_not": [{"bool": {"filter": [{"match": {"field": "value"}}, {"match": {"field2": "value2"}}]}}]},
|
|
)
|
|
|
|
def test_optimizations(self):
|
|
self.validate(
|
|
"(field:value or field2:value2) and field3:value3",
|
|
{
|
|
"should": [{"match": {"field": "value"}}, {"match": {"field2": "value2"}}],
|
|
"filter": [{"match": {"field3": "value3"}}],
|
|
"minimum_should_match": 1,
|
|
},
|
|
)
|
|
|
|
self.validate(
|
|
"(field:value and field2:value2) or field3:value3",
|
|
{
|
|
"should": [
|
|
{"bool": {"filter": [{"match": {"field": "value"}}, {"match": {"field2": "value2"}}]}},
|
|
{"match": {"field3": "value3"}},
|
|
],
|
|
"minimum_should_match": 1,
|
|
},
|
|
)
|
|
|
|
self.validate(
|
|
"a:(v1 or v2 or v3) or b:(v4 or v5)",
|
|
{
|
|
"should": [
|
|
{"match": {"a": "v1"}},
|
|
{"match": {"a": "v2"}},
|
|
{"match": {"a": "v3"}},
|
|
{"match": {"b": "v4"}},
|
|
{"match": {"b": "v5"}},
|
|
],
|
|
"minimum_should_match": 1,
|
|
},
|
|
)
|
|
|
|
self.validate(
|
|
"a:(v1 or v2 or v3) and b:(v4 or v5)",
|
|
{
|
|
"should": [{"match": {"a": "v1"}}, {"match": {"a": "v2"}}, {"match": {"a": "v3"}}],
|
|
"filter": [
|
|
{"bool": {"should": [{"match": {"b": "v4"}}, {"match": {"b": "v5"}}], "minimum_should_match": 1}}
|
|
],
|
|
"minimum_should_match": 1,
|
|
},
|
|
)
|
|
|
|
self.validate(
|
|
"(field:value and not field2:value2) or field3:value3",
|
|
{
|
|
"should": [
|
|
{
|
|
"bool": {
|
|
"filter": [{"match": {"field": "value"}}],
|
|
"must_not": [{"match": {"field2": "value2"}}],
|
|
}
|
|
},
|
|
{"match": {"field3": "value3"}},
|
|
],
|
|
"minimum_should_match": 1,
|
|
},
|
|
)
|