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

(cherry picked from commit 039a7d1c68f6f1ed0e7e6cfb86be6b04eec8051c)
This commit is contained in:
Andrei Stefan 2020-08-19 12:40:48 +03:00 committed by GitHub
parent be4ebfbf46
commit a6c0670a14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 5 deletions

View File

@ -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,

View File

@ -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.Arrays;
@ -42,6 +45,7 @@ final class QueryTranslator {
new ExpressionTranslators.StringQueries(),
new ExpressionTranslators.Matches(),
new ExpressionTranslators.MultiMatches(),
new CaseSensitiveScalarFunctions(),
new Scalars()
);
@ -113,4 +117,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;
}
}
}

View File

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

View File

@ -189,12 +189,18 @@ process where startsWith(user_name, 'A') or startsWith(user_name, 'B')
{"prefix":{"user_name":{"value":"B","boost":1.0}}}],"adjust_pure_negative":true,"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}}}],"adjust_pure_negative":true,"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}}}],"adjust_pure_negative":true,"boost":1.0}}
;
stringContains-caseInsensitive