Explorar o código

Do not filter source if exclude contains `*` (#108501)

This commit prevents the serialization of source if not needed.
Ignacio Vera hai 1 ano
pai
achega
7ed58e75da

+ 8 - 3
server/src/main/java/org/elasticsearch/search/fetch/subphase/FetchSourcePhase.java

@@ -28,7 +28,7 @@ public final class FetchSourcePhase implements FetchSubPhase {
         }
         assert fetchSourceContext.fetchSource();
         SourceFilter sourceFilter = fetchSourceContext.filter();
-
+        final boolean filterExcludesAll = sourceFilter.excludesAll();
         return new FetchSubPhaseProcessor() {
             private int fastPath;
 
@@ -67,8 +67,13 @@ public final class FetchSourcePhase implements FetchSubPhase {
                     return;
                 }
 
-                // Otherwise, filter the source and add it to the hit.
-                source = source.filter(sourceFilter);
+                if (filterExcludesAll) {
+                    // we can just add an empty map
+                    source = Source.empty(source.sourceContentType());
+                } else {
+                    // Otherwise, filter the source and add it to the hit.
+                    source = source.filter(sourceFilter);
+                }
                 if (nestedHit) {
                     source = extractNested(source, hitContext.hit().getNestedIdentity());
                 }

+ 4 - 0
server/src/main/java/org/elasticsearch/search/lookup/SourceFilter.java

@@ -109,4 +109,8 @@ public final class SourceFilter {
             }
         };
     }
+
+    public boolean excludesAll() {
+        return Arrays.asList(excludes).contains("*");
+    }
 }

+ 21 - 0
server/src/test/java/org/elasticsearch/search/fetch/subphase/FetchSourcePhaseTests.java

@@ -52,6 +52,27 @@ public class FetchSourcePhaseTests extends ESTestCase {
         assertEquals(Collections.singletonMap("field1", "value"), hitContext.hit().getSourceAsMap());
     }
 
+    public void testExcludesAll() throws IOException {
+        XContentBuilder source = XContentFactory.jsonBuilder().startObject().field("field1", "value").field("field2", "value2").endObject();
+        HitContext hitContext = hitExecute(source, false, null, null);
+        assertNull(hitContext.hit().getSourceAsMap());
+
+        hitContext = hitExecute(source, true, "field1", "*");
+        assertEquals(Collections.emptyMap(), hitContext.hit().getSourceAsMap());
+
+        hitContext = hitExecute(source, true, null, "*");
+        assertEquals(Collections.emptyMap(), hitContext.hit().getSourceAsMap());
+
+        hitContext = hitExecute(source, true, "*", "*");
+        assertEquals(Collections.emptyMap(), hitContext.hit().getSourceAsMap());
+
+        hitContext = hitExecuteMultiple(source, true, new String[] { "field1", "field2" }, new String[] { "*", "field1" });
+        assertEquals(Collections.emptyMap(), hitContext.hit().getSourceAsMap());
+
+        hitContext = hitExecuteMultiple(source, true, null, new String[] { "field2", "*", "field1" });
+        assertEquals(Collections.emptyMap(), hitContext.hit().getSourceAsMap());
+    }
+
     public void testMultipleFiltering() throws IOException {
         XContentBuilder source = XContentFactory.jsonBuilder().startObject().field("field", "value").field("field2", "value2").endObject();
         HitContext hitContext = hitExecuteMultiple(source, true, new String[] { "*.notexisting", "field" }, null);