Forráskód Böngészése

EQL: make stringContains function use a wildcard ES query wherever possible (#61189)

Andrei Stefan 5 éve
szülő
commit
039a7d1c68

+ 8 - 0
x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/expression/function/scalar/string/StringContains.java

@@ -58,6 +58,14 @@ public class StringContains extends CaseSensitiveScalarFunction {
         return isStringAndExact(substring, sourceText(), Expressions.ParamOrdinal.SECOND);
     }
 
+    public Expression string() {
+        return string;
+    }
+
+    public Expression substring() {
+        return substring;
+    }
+
     @Override
     protected Pipe makePipe() {
         return new StringContainsFunctionPipe(source(), this,

+ 34 - 0
x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/planner/QueryTranslator.java

@@ -7,11 +7,13 @@
 package org.elasticsearch.xpack.eql.planner;
 
 import org.elasticsearch.xpack.eql.expression.function.scalar.string.CIDRMatch;
+import org.elasticsearch.xpack.eql.expression.function.scalar.string.StringContains;
 import org.elasticsearch.xpack.ql.QlIllegalArgumentException;
 import org.elasticsearch.xpack.ql.expression.Expression;
 import org.elasticsearch.xpack.ql.expression.Expressions;
 import org.elasticsearch.xpack.ql.expression.FieldAttribute;
 import org.elasticsearch.xpack.ql.expression.function.scalar.ScalarFunction;
+import org.elasticsearch.xpack.ql.expression.function.scalar.string.CaseSensitiveScalarFunction;
 import org.elasticsearch.xpack.ql.expression.predicate.logical.And;
 import org.elasticsearch.xpack.ql.expression.predicate.logical.Or;
 import org.elasticsearch.xpack.ql.planner.ExpressionTranslator;
@@ -20,6 +22,7 @@ import org.elasticsearch.xpack.ql.planner.TranslatorHandler;
 import org.elasticsearch.xpack.ql.querydsl.query.Query;
 import org.elasticsearch.xpack.ql.querydsl.query.ScriptQuery;
 import org.elasticsearch.xpack.ql.querydsl.query.TermsQuery;
+import org.elasticsearch.xpack.ql.querydsl.query.WildcardQuery;
 import org.elasticsearch.xpack.ql.util.CollectionUtils;
 
 import java.util.LinkedHashSet;
@@ -41,6 +44,7 @@ final class QueryTranslator {
             new ExpressionTranslators.StringQueries(),
             new ExpressionTranslators.Matches(),
             new ExpressionTranslators.MultiMatches(),
+            new CaseSensitiveScalarFunctions(),
             new Scalars()
     );
 
@@ -112,4 +116,34 @@ final class QueryTranslator {
             return handler.wrapFunctionQuery(f, f, new ScriptQuery(f.source(), f.asScript()));
         }
     }
+
+    public static class CaseSensitiveScalarFunctions extends ExpressionTranslator<CaseSensitiveScalarFunction> {
+
+        @Override
+        protected Query asQuery(CaseSensitiveScalarFunction f, TranslatorHandler handler) {
+            return f.isCaseSensitive() ? doTranslate(f, handler) : null;
+        }
+
+        public static Query doTranslate(CaseSensitiveScalarFunction f, TranslatorHandler handler) {
+            Expression field = null;
+            Expression constant = null;
+
+            if (f instanceof StringContains) {
+                StringContains sc = (StringContains) f;
+                field = sc.string();
+                constant = sc.substring();
+            } else {
+                return null;
+            }
+
+            if (field instanceof FieldAttribute && constant.foldable()) {
+                String targetFieldName = handler.nameOf(((FieldAttribute) field).exactAttribute());
+                String substring = (String) constant.fold();
+
+                return new WildcardQuery(f.source(), targetFieldName, "*" + substring + "*");
+            }
+
+            return null;
+        }
+    }
 }

+ 1 - 1
x-pack/plugin/eql/src/test/resources/mapping-default.json

@@ -56,7 +56,7 @@
             "type" : "text",
             "fields" : {
                 "keyword" : {
-                    "type" : "keyword",
+                    "type" : "wildcard",
                     "ignore_above" : 256
                 }
             }

+ 10 - 4
x-pack/plugin/eql/src/test/resources/queryfolder_tests.txt

@@ -189,12 +189,18 @@ process where startsWith(user_name, 'A') or startsWith(user_name, 'B')
 {"prefix":{"user_name":{"value":"B","boost":1.0}}}],"boost":1.0}}],"boost":1.0}}
 ;
 
-stringContains-caseSensitive
+stringContainsExactField-caseSensitive
 process where stringContains(process_name, "foo")
 ;
-"script":{"source":"InternalQlScriptUtils.nullSafeFilter(InternalEqlScriptUtils.stringContains(
-InternalQlScriptUtils.docValue(doc,params.v0),params.v1,params.v2))"
-"params":{"v0":"process_name","v1":"foo","v2":true}
+{"bool":{"must":[{"term":{"event.category":{"value":"process","boost":1.0}}},
+{"wildcard":{"process_name":{"wildcard":"*foo*","boost":1.0}}}],"boost":1.0}}
+;
+
+stringContainsExactSubField-caseSensitive
+process where stringContains(hostname, "foo")
+;
+{"bool":{"must":[{"term":{"event.category":{"value":"process","boost":1.0}}},
+{"wildcard":{"hostname.keyword":{"wildcard":"*foo*","boost":1.0}}}],"boost":1.0}}
 ;
 
 stringContains-caseInsensitive