浏览代码

Scripting: Fix expressions to temporarily support filter scripts (#26824)

This commit adds a hack converting 0.0 to false and non-zero to true for
expressions operating under a filter context.

closes #26429
Ryan Ernst 8 年之前
父节点
当前提交
6b53dadcf9

+ 25 - 0
modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionScriptEngine.java

@@ -38,6 +38,7 @@ import org.elasticsearch.index.mapper.MappedFieldType;
 import org.elasticsearch.index.mapper.MapperService;
 import org.elasticsearch.script.ClassPermission;
 import org.elasticsearch.script.ExecutableScript;
+import org.elasticsearch.script.FilterScript;
 import org.elasticsearch.script.ScriptContext;
 import org.elasticsearch.script.ScriptEngine;
 import org.elasticsearch.script.ScriptException;
@@ -107,6 +108,9 @@ public class ExpressionScriptEngine extends AbstractComponent implements ScriptE
         } else if (context.instanceClazz.equals(ExecutableScript.class)) {
             ExecutableScript.Factory factory = (p) -> new ExpressionExecutableScript(expr, p);
             return context.factoryClazz.cast(factory);
+        } else if (context.instanceClazz.equals(FilterScript.class)) {
+            FilterScript.Factory factory = (p, lookup) -> newFilterScript(expr, lookup, p);
+            return context.factoryClazz.cast(factory);
         }
         throw new IllegalArgumentException("expression engine does not know how to handle script context [" + context.name + "]");
     }
@@ -236,6 +240,27 @@ public class ExpressionScriptEngine extends AbstractComponent implements ScriptE
         return new ExpressionSearchScript(expr, bindings, specialValue, needsScores);
     }
 
+    /**
+     * This is a hack for filter scripts, which must return booleans instead of doubles as expression do.
+     * See https://github.com/elastic/elasticsearch/issues/26429.
+     */
+    private FilterScript.LeafFactory newFilterScript(Expression expr, SearchLookup lookup, @Nullable Map<String, Object> vars) {
+        SearchScript.LeafFactory searchLeafFactory = newSearchScript(expr, lookup, vars);
+        return ctx -> {
+            SearchScript script = searchLeafFactory.newInstance(ctx);
+            return new FilterScript(vars, lookup, ctx) {
+                @Override
+                public boolean execute() {
+                    return script.runAsDouble() != 0.0;
+                }
+                @Override
+                public void setDocument(int docid) {
+                    script.setDocument(docid);
+                }
+            };
+        };
+    }
+
     /**
      * converts a ParseException at compile-time or link-time to a ScriptException
      */

+ 15 - 0
modules/lang-expression/src/test/java/org/elasticsearch/script/expression/MoreExpressionTests.java

@@ -700,4 +700,19 @@ public class MoreExpressionTests extends ESIntegTestCase {
         assertEquals(2.0D, rsp.getHits().getAt(1).field("foo").getValue(), 1.0D);
         assertEquals(2.0D, rsp.getHits().getAt(2).field("foo").getValue(), 1.0D);
     }
+
+    public void testFilterScript() throws Exception {
+        createIndex("test");
+        ensureGreen("test");
+        indexRandom(true,
+            client().prepareIndex("test", "doc", "1").setSource("foo", 1.0),
+            client().prepareIndex("test", "doc", "2").setSource("foo", 0.0));
+        SearchRequestBuilder builder = buildRequest("doc['foo'].value");
+        Script script = new Script(ScriptType.INLINE, "expression", "doc['foo'].value", Collections.emptyMap());
+        builder.setQuery(QueryBuilders.boolQuery().filter(QueryBuilders.scriptQuery(script)));
+        SearchResponse rsp = builder.get();
+        assertSearchResponse(rsp);
+        assertEquals(1, rsp.getHits().getTotalHits());
+        assertEquals(1.0D, rsp.getHits().getAt(0).field("foo").getValue(), 0.0D);
+    }
 }