You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by fo...@apache.org on 2021/09/14 06:40:45 UTC

[jackrabbit-oak] branch trunk updated: OAK-9572: index aggregations should ignore hidden properties (#368)

This is an automated email from the ASF dual-hosted git repository.

fortino pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 52bb236  OAK-9572: index aggregations should ignore hidden properties (#368)
52bb236 is described below

commit 52bb236197cfc840d8120d3d5368135370a72f6d
Author: Fabrizio Fortino <fa...@gmail.com>
AuthorDate: Tue Sep 14 08:40:36 2021 +0200

    OAK-9572: index aggregations should ignore hidden properties (#368)
    
    * OAK-9572: skip hidden properties while collecting aggregations
    
    * OAK-9572: (improvements) reduced use of guava
    
    * OAK-9572: add unit test
    
    * OAK-9572: (improvements) cleanup AggregateTest
    
    * OAK-9572: (minor) fixed modifier
    
    * OAK-9572: (test) include also hidden nodes
---
 .../elastic/ElasticDynamicBoostQueryTest.java      | 61 ++++++--------
 .../oak/plugins/index/search/Aggregate.java        | 53 +++++-------
 .../oak/plugins/index/search/AggregateTest.java    | 95 +++++++++++++---------
 3 files changed, 104 insertions(+), 105 deletions(-)

diff --git a/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticDynamicBoostQueryTest.java b/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticDynamicBoostQueryTest.java
index 6ed25aa..4098d77 100644
--- a/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticDynamicBoostQueryTest.java
+++ b/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticDynamicBoostQueryTest.java
@@ -27,7 +27,6 @@ import org.apache.jackrabbit.oak.plugins.nodetype.write.NodeTypeRegistry;
 import org.junit.Test;
 
 import java.io.ByteArrayInputStream;
-import java.io.InputStream;
 import java.util.Arrays;
 import java.util.UUID;
 
@@ -35,7 +34,7 @@ import static org.apache.jackrabbit.JcrConstants.NT_UNSTRUCTURED;
 
 public class ElasticDynamicBoostQueryTest extends ElasticAbstractQueryTest {
 
-    public static final String ASSET_NODE_TYPE =
+    private static final String ASSET_NODE_TYPE =
             "[dam:Asset]\n" +
                     " - * (UNDEFINED) multiple\n" +
                     " - * (UNDEFINED)\n" +
@@ -47,20 +46,16 @@ public class ElasticDynamicBoostQueryTest extends ElasticAbstractQueryTest {
 
         Tree test = createNodeWithType(root.getTree("/"), "test", NT_UNSTRUCTURED);
         Tree item1Metadata = createNodeWithMetadata(test, "item1", "flower with a lot of red and a bit of blue");
-        Tree item1Color1 = createNodeWithType(item1Metadata,"color1", NT_UNSTRUCTURED);
-        item1Color1.setProperty("name", "red");
-        item1Color1.setProperty("confidence", 9.0);
-        Tree item1Color2 = createNodeWithType(item1Metadata,"color2", NT_UNSTRUCTURED);
-        item1Color2.setProperty("name", "blue");
-        item1Color2.setProperty("confidence", 1.0);
+        Tree item1Color1 = createNodeWithType(item1Metadata, "color1", NT_UNSTRUCTURED);
+        configureBoostedField(item1Color1, "red", 9.0);
+        Tree item1Color2 = createNodeWithType(item1Metadata, "color2", NT_UNSTRUCTURED);
+        configureBoostedField(item1Color2, "blue", 1.0);
 
         Tree item2Metadata = createNodeWithMetadata(test, "item2", "flower with a lot of blue and a bit of red");
-        Tree item2Color1 = createNodeWithType(item2Metadata,"color1", NT_UNSTRUCTURED);
-        item2Color1.setProperty("name", "blue");
-        item2Color1.setProperty("confidence", 9.0);
-        Tree item2Color2 = createNodeWithType(item2Metadata,"color2", NT_UNSTRUCTURED);
-        item2Color2.setProperty("name", "red");
-        item2Color2.setProperty("confidence", 1.0);
+        Tree item2Color1 = createNodeWithType(item2Metadata, "color1", NT_UNSTRUCTURED);
+        configureBoostedField(item2Color1, "blue", 9.0);
+        Tree item2Color2 = createNodeWithType(item2Metadata, "color2", NT_UNSTRUCTURED);
+        configureBoostedField(item2Color2, "red", 1.0);
         root.commit();
 
         assertEventually(() -> {
@@ -81,19 +76,15 @@ public class ElasticDynamicBoostQueryTest extends ElasticAbstractQueryTest {
         Tree item1Metadata = createNodeWithMetadata(test, "item1", "flower with a lot of red and a bit of blue");
         item1Metadata.setProperty("foo", "bar");
         Tree item1Color1 = createNodeWithType(item1Metadata,"color1", NT_UNSTRUCTURED);
-        item1Color1.setProperty("name", "red");
-        item1Color1.setProperty("confidence", 9.0);
+        configureBoostedField(item1Color1, "red", 9.0);
         Tree item1Color2 = createNodeWithType(item1Metadata,"color2", NT_UNSTRUCTURED);
-        item1Color2.setProperty("name", "blue");
-        item1Color2.setProperty("confidence", 1.0);
+        configureBoostedField(item1Color2, "blue", 1.0);
 
         Tree item2Metadata = createNodeWithMetadata(test, "item2", "flower with a lot of blue and a bit of red");
         Tree item2Color1 = createNodeWithType(item2Metadata,"color1", NT_UNSTRUCTURED);
-        item2Color1.setProperty("name", "blue");
-        item2Color1.setProperty("confidence", 9.0);
+        configureBoostedField(item2Color1, "blue", 9.0);
         Tree item2Color2 = createNodeWithType(item2Metadata,"color2", NT_UNSTRUCTURED);
-        item2Color2.setProperty("name", "red");
-        item2Color2.setProperty("confidence", 1.0);
+        configureBoostedField(item2Color2, "red", 1.0);
         root.commit();
 
         assertEventually(() -> {
@@ -113,19 +104,15 @@ public class ElasticDynamicBoostQueryTest extends ElasticAbstractQueryTest {
         Tree test = createNodeWithType(root.getTree("/"), "test", NT_UNSTRUCTURED);
         Tree item1Metadata = createNodeWithMetadata(test, "item1", "flower with a lot of colors");
         Tree item1Color1 = createNodeWithType(item1Metadata,"color1", NT_UNSTRUCTURED);
-        item1Color1.setProperty("name", "red");
-        item1Color1.setProperty("confidence", 9.0);
+        configureBoostedField(item1Color1, "red", 9.0);
         Tree item1Color2 = createNodeWithType(item1Metadata,"color2", NT_UNSTRUCTURED);
-        item1Color2.setProperty("name", "blue");
-        item1Color2.setProperty("confidence", 1.0);
+        configureBoostedField(item1Color2, "blue", 1.0);
 
         Tree item2Metadata = createNodeWithMetadata(test, "item2", "flower with a lot of colors");
         Tree item2Color1 = createNodeWithType(item2Metadata,"color1", NT_UNSTRUCTURED);
-        item2Color1.setProperty("name", "blue");
-        item2Color1.setProperty("confidence", 9.0);
+        configureBoostedField(item2Color1, "blue", 9.0);
         Tree item2Color2 = createNodeWithType(item2Metadata,"color2", NT_UNSTRUCTURED);
-        item2Color2.setProperty("name", "red");
-        item2Color2.setProperty("confidence", 1.0);
+        configureBoostedField(item2Color2, "red", 1.0);
         root.commit();
 
         assertEventually(() -> {
@@ -138,8 +125,14 @@ public class ElasticDynamicBoostQueryTest extends ElasticAbstractQueryTest {
         });
     }
 
+    private void configureBoostedField(Tree node, String name, double confidence) {
+        node.setProperty("name", name);
+        node.orderBefore(null);
+        node.setProperty("confidence", confidence);
+    }
+
     private void configureIndex() throws CommitFailedException {
-        NodeTypeRegistry.register(root, toInputStream(ASSET_NODE_TYPE), "test nodeType");
+        NodeTypeRegistry.register(root, new ByteArrayInputStream(ASSET_NODE_TYPE.getBytes()), "test nodeType");
         IndexDefinitionBuilder builder = createIndex(true, "dam:Asset", "title", "dynamicBoost");
         IndexDefinitionBuilder.PropertyRule title = builder.indexRule("dam:Asset")
                 .property("title")
@@ -164,13 +157,9 @@ public class ElasticDynamicBoostQueryTest extends ElasticAbstractQueryTest {
                 "metadata", NT_UNSTRUCTURED);
     }
 
-    private static Tree createNodeWithType(Tree t, String nodeName, String typeName){
+    private Tree createNodeWithType(Tree t, String nodeName, String typeName){
         t = t.addChild(nodeName);
         t.setProperty(JcrConstants.JCR_PRIMARYTYPE, typeName, Type.NAME);
         return t;
     }
-
-    private static InputStream toInputStream(String x) {
-        return new ByteArrayInputStream(x.getBytes());
-    }
 }
diff --git a/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/Aggregate.java b/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/Aggregate.java
index 2b1729f..eb67317 100644
--- a/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/Aggregate.java
+++ b/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/Aggregate.java
@@ -19,30 +19,27 @@
 
 package org.apache.jackrabbit.oak.plugins.index.search;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.regex.Pattern;
 
-import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.plugins.index.search.util.ConfigUtil;
 import org.apache.jackrabbit.oak.plugins.memory.MemoryChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
 import org.jetbrains.annotations.Nullable;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.collect.Iterables.toArray;
-import static com.google.common.collect.Lists.newArrayList;
-import static com.google.common.collect.Lists.newArrayListWithCapacity;
 import static org.apache.jackrabbit.oak.commons.PathUtils.elements;
 import static org.apache.jackrabbit.oak.commons.PathUtils.getParentPath;
 
@@ -53,7 +50,7 @@ import static org.apache.jackrabbit.oak.commons.PathUtils.getParentPath;
  * stored in child nodes; say /x/section1 contains "Hello" and /x/section2
  * contains "World". If index aggregation is configured correctly, it will
  * combine all the text of the child nodes, and index that as /x. When doing a
- * fulltext search for for "Hello World", the index will then return /x.
+ * fulltext search for "Hello World", the index will then return /x.
  */
 public class Aggregate {
 
@@ -80,10 +77,10 @@ public class Aggregate {
     Aggregate(String nodeTypeName, List<? extends Include> includes,
               int recursionLimit) {
         this.nodeTypeName = nodeTypeName;
-        this.includes = ImmutableList.copyOf(includes);
+        this.includes = Collections.unmodifiableList(includes);
         this.reAggregationLimit = recursionLimit;
         this.relativeNodeIncludes = findRelativeNodeIncludes(includes);
-        this.nodeAggregates = hasNodeIncludes(includes);
+        this.nodeAggregates = includes.stream().anyMatch(input -> input instanceof NodeInclude);
     }
 
     public List<? extends Include> getIncludes() {
@@ -98,7 +95,7 @@ public class Aggregate {
     }
 
     public List<Matcher> createMatchers(AggregateRoot root){
-        List<Matcher> matchers = newArrayListWithCapacity(includes.size());
+        List<Matcher> matchers = new ArrayList<>(includes.size());
         for (Include include : includes) {
             matchers.add(new Matcher(this, include, root));
         }
@@ -147,7 +144,7 @@ public class Aggregate {
 
     private static void collectAggregatesForDirectMatchers(NodeState nodeState, List<Matcher> matchers,
                                                            ResultCollector collector) {
-        Map<String, ChildNodeEntry> children = Maps.newHashMap();
+        Map<String, ChildNodeEntry> children = new HashMap<>();
         //Collect potentially matching child nodestates based on matcher name
         for (Matcher m : matchers){
             String nodeName = m.getNodeName();
@@ -167,7 +164,7 @@ public class Aggregate {
     private static void matchChildren(List<Matcher> matchers, ResultCollector collector,
                                       Iterable<? extends ChildNodeEntry> children) {
         for (ChildNodeEntry cne : children) {
-            List<Matcher> nextSet = newArrayListWithCapacity(matchers.size());
+            List<Matcher> nextSet = new ArrayList<>(matchers.size());
             for (Matcher m : matchers) {
                 Matcher result = m.match(cne.getName(), cne.getNodeState());
                 if (result.getStatus() == Matcher.Status.MATCH_FOUND){
@@ -194,7 +191,7 @@ public class Aggregate {
     }
 
     private List<Matcher> createMatchers() {
-        List<Matcher> matchers = newArrayListWithCapacity(includes.size());
+        List<Matcher> matchers = new ArrayList<>(includes.size());
         for (Include include : includes) {
             matchers.add(new Matcher(this, include));
         }
@@ -202,7 +199,7 @@ public class Aggregate {
     }
 
     private static List<NodeInclude> findRelativeNodeIncludes(List<? extends Include> includes) {
-        List<NodeInclude> result = newArrayList();
+        List<NodeInclude> result = new ArrayList<>();
         for (Include i : includes){
             if (i instanceof NodeInclude){
                 NodeInclude ni = (NodeInclude) i;
@@ -211,16 +208,7 @@ public class Aggregate {
                 }
             }
         }
-        return ImmutableList.copyOf(result);
-    }
-
-    private static boolean hasNodeIncludes(List<? extends Include> includes) {
-        return Iterables.any(includes, new Predicate<Include>() {
-            @Override
-            public boolean apply(Include input) {
-                return input instanceof NodeInclude;
-            }
-        });
+        return Collections.unmodifiableList(result);
     }
 
     public interface AggregateMapper {
@@ -393,17 +381,20 @@ public class Aggregate {
             }
         }
 
+        /**
+         * Collect the aggregated results ignoring hidden properties
+         */
         @Override
         public void collectResults(String nodePath, NodeState nodeState, ResultCollector results) {
             if (pattern != null) {
                 for (PropertyState ps : nodeState.getProperties()) {
-                    if (pattern.matcher(ps.getName()).matches()) {
+                    if (!NodeStateUtils.isHidden(ps.getName()) && pattern.matcher(ps.getName()).matches()) {
                         results.onResult(new PropertyIncludeResult(ps, propertyDefinition, parentPath));
                     }
                 }
             } else {
                 PropertyState ps = nodeState.getProperty(propertyName);
-                if (ps != null) {
+                if (ps != null && !NodeStateUtils.isHidden(ps.getName())) {
                     results.onResult(new PropertyIncludeResult(ps, propertyDefinition, parentPath));
                 }
             }
@@ -568,9 +559,9 @@ public class Aggregate {
             this.matchedNodeState = null;
             this.currentPath = currentPath;
 
-            List<String> paths = newArrayList(m.aggregateStack);
+            List<String> paths = new ArrayList<>(m.aggregateStack);
             paths.add(currentPath);
-            this.aggregateStack = ImmutableList.copyOf(paths);
+            this.aggregateStack = Collections.unmodifiableList(paths);
         }
 
         public boolean isPatternBased() {
@@ -610,7 +601,7 @@ public class Aggregate {
                         return Collections.emptyList();
                     }
 
-                    List<Matcher> result = Lists.newArrayListWithCapacity(nextAgg.includes.size());
+                    List<Matcher> result = new ArrayList<>(nextAgg.includes.size());
                     for (Include i : nextAgg.includes){
                         result.add(new Matcher(this,  i, currentPath));
                     }
@@ -626,8 +617,8 @@ public class Aggregate {
         public void collectResults(ResultCollector results) {
             checkArgument(status == Status.MATCH_FOUND);
 
-            //If result being collected as part of reaggregation then take path
-            //from the stack otherwise its the current path
+            //If result being collected as part of re-aggregation then take path
+            //from the stack otherwise it's the current path
             String rootIncludePath = aggregateStack.isEmpty() ?  currentPath : aggregateStack.get(0);
             currentInclude.collectResults(rootState.rootInclude, rootIncludePath,
                     currentPath, matchedNodeState, results);
diff --git a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/AggregateTest.java b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/AggregateTest.java
index 528b6f2..fb934c5 100644
--- a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/AggregateTest.java
+++ b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/AggregateTest.java
@@ -19,17 +19,19 @@
 
 package org.apache.jackrabbit.oak.plugins.index.search;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import com.google.common.base.Function;
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.ListMultimap;
-import com.google.common.collect.Lists;
 import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.commons.PathUtils;
@@ -41,10 +43,8 @@ import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.junit.Test;
 
-import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.collect.ImmutableList.of;
 import static com.google.common.collect.Iterables.toArray;
-import static com.google.common.collect.Maps.newHashMap;
 import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
 import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
 import static org.apache.jackrabbit.oak.InitialContentHelper.INITIAL_CONTENT;
@@ -53,10 +53,10 @@ import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE
 import static org.hamcrest.CoreMatchers.hasItems;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.lessThanOrEqualTo;
+import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
@@ -71,7 +71,7 @@ public class AggregateTest {
     //~---------------------------------< Node Includes >
 
     @Test
-    public void oneLevelAll() throws Exception{
+    public void oneLevelAll() {
         Aggregate ag = new Aggregate("nt:base", of(ni("*")));
         NodeBuilder nb = newNode("nt:base");
         nb.child("a").child("c");
@@ -83,7 +83,7 @@ public class AggregateTest {
     }
 
     @Test
-    public void oneLevelNamed() throws Exception{
+    public void oneLevelNamed() {
         Aggregate ag = new Aggregate("nt:base", of(ni("a")));
         NodeBuilder nb = newNode("nt:base");
         nb.child("a");
@@ -95,7 +95,7 @@ public class AggregateTest {
     }
 
     @Test
-    public void noOfChildNodeRead() throws Exception{
+    public void noOfChildNodeRead() {
         Aggregate ag = new Aggregate("nt:base", of(ni("a")));
         NodeBuilder nb = newNode("nt:base");
         nb.child("a");
@@ -106,13 +106,10 @@ public class AggregateTest {
         NodeState state = nb.getNodeState();
         final AtomicInteger counter = new AtomicInteger();
         Iterable<? extends ChildNodeEntry> countingIterator = Iterables.transform(state.getChildNodeEntries(),
-                new Function<ChildNodeEntry, ChildNodeEntry>() {
-            @Override
-            public ChildNodeEntry apply(ChildNodeEntry input) {
-                counter.incrementAndGet();
-                return input;
-            }
-        });
+                (Function<ChildNodeEntry, ChildNodeEntry>) input -> {
+                    counter.incrementAndGet();
+                    return input;
+                });
         NodeState mocked = spy(state);
         doReturn(countingIterator).when(mocked).getChildNodeEntries();
         ag.collectAggregates(mocked, col);
@@ -122,7 +119,7 @@ public class AggregateTest {
     }
 
     @Test
-    public void oneLevelTyped() throws Exception{
+    public void oneLevelTyped() {
         Aggregate ag = new Aggregate("nt:base", of(ni("nt:resource","*", false)));
         NodeBuilder nb = newNode("nt:base");
         nb.child("a").setProperty(JCR_PRIMARYTYPE,"nt:resource");
@@ -134,7 +131,7 @@ public class AggregateTest {
     }
 
     @Test
-    public void oneLevelTypedMixin() throws Exception{
+    public void oneLevelTypedMixin() {
         Aggregate ag = new Aggregate("nt:base", of(ni("mix:title","*", false)));
         NodeBuilder nb = newNode("nt:base");
         nb.child("a").setProperty(JcrConstants.JCR_MIXINTYPES, Collections.singleton("mix:title"), Type.NAMES);
@@ -146,7 +143,7 @@ public class AggregateTest {
     }
 
     @Test
-    public void multiLevelAll() throws Exception{
+    public void multiLevelAll() {
         Aggregate ag = new Aggregate("nt:base", of(ni("*"), ni("*/*")));
         NodeBuilder nb = newNode("nt:base");
         nb.child("a").child("c");
@@ -159,7 +156,7 @@ public class AggregateTest {
     }
 
     @Test
-    public void multiLevelNamed() throws Exception{
+    public void multiLevelNamed() {
         Aggregate ag = new Aggregate("nt:base", of(ni("a"), ni("d/e")));
         NodeBuilder nb = newNode("nt:base");
         nb.child("a").child("c");
@@ -172,7 +169,7 @@ public class AggregateTest {
     }
 
     @Test
-    public void multiLevelTyped() throws Exception{
+    public void multiLevelTyped() {
         Aggregate ag = new Aggregate("nt:base", of(ni("a"),
                 ni("nt:resource", "d/*/*", false)));
         NodeBuilder nb = newNode("nt:base");
@@ -188,7 +185,7 @@ public class AggregateTest {
     }
 
     @Test
-    public void multiLevelNamedSubAll() throws Exception{
+    public void multiLevelNamedSubAll() {
         Aggregate ag = new Aggregate("nt:base", of(ni("a"), ni("d/*/*")));
         NodeBuilder nb = newNode("nt:base");
         nb.child("a").child("c");
@@ -205,7 +202,7 @@ public class AggregateTest {
     //~---------------------------------< Node include recursive >
 
     @Test
-    public void multiAggregateMapping() throws Exception{
+    public void multiAggregateMapping() {
         Aggregate ag = new Aggregate("nt:base", of(ni("*")));
 
         Aggregate agFile = new Aggregate("nt:file", of(ni("*"), ni("*/*")));
@@ -223,7 +220,7 @@ public class AggregateTest {
     }
 
     @Test
-    public void recursionEnabled() throws Exception{
+    public void recursionEnabled() {
         Aggregate agFile = new Aggregate("nt:file", of(ni("*")), 5);
         mapper.add("nt:file", agFile);
 
@@ -239,12 +236,12 @@ public class AggregateTest {
     }
 
     @Test
-    public void recursionEnabledWithLimitCheck() throws Exception{
+    public void recursionEnabledWithLimitCheck() {
         int limit = 5;
         Aggregate agFile = new Aggregate("nt:file", of(ni("*")), limit);
         mapper.add("nt:file", agFile);
 
-        List<String> expectedPaths = Lists.newArrayList();
+        List<String> expectedPaths = new ArrayList<>();
         NodeBuilder nb = newNode("nt:file");
         nb.child("a").child("c");
 
@@ -268,13 +265,12 @@ public class AggregateTest {
     }
 
     @Test
-    public void includeMatches() throws Exception{
+    public void includeMatches() {
         Aggregate ag = new Aggregate("nt:base", of(ni(null, "*", true), ni(null, "*/*", true)));
         assertTrue(ag.hasRelativeNodeInclude("foo"));
         assertTrue(ag.hasRelativeNodeInclude("foo/bar"));
         assertFalse(ag.hasRelativeNodeInclude("foo/bar/baz"));
 
-
         Aggregate ag2 = new Aggregate("nt:base", of(ni(null, "foo", true), ni(null, "foo/*", true)));
         assertTrue(ag2.hasRelativeNodeInclude("foo"));
         assertFalse(ag2.hasRelativeNodeInclude("bar"));
@@ -283,7 +279,7 @@ public class AggregateTest {
     }
 
     @Test
-    public void testReaggregate() throws Exception{
+    public void testReaggregate() {
         //Enable relative include for all child nodes of nt:folder
         //So indexing would create fulltext field for each relative nodes
         Aggregate agFolder = new Aggregate("nt:folder", of(ni("nt:file", "*", true)));
@@ -309,7 +305,7 @@ public class AggregateTest {
     }
 
     @Test
-    public void testReaggregateMixin() throws Exception{
+    public void testReaggregateMixin() {
         //A variant of testReaggregation but using mixin
         //instead of normal nodetype. It abuses mix:title
         //and treat it like nt:file. Test check if reaggregation
@@ -340,7 +336,7 @@ public class AggregateTest {
     }
 
     @Test
-    public void testRelativeNodeInclude() throws Exception{
+    public void testRelativeNodeInclude() {
         //Enable relative include for all child nodes of nt:folder
         //So indexing would create fulltext field for each relative nodes
         Aggregate agContent = new Aggregate("app:Page", of(ni(null, "jcr:content", true)));
@@ -367,7 +363,7 @@ public class AggregateTest {
     }
 
     private static void createFileMixin(NodeBuilder nb, String fileName, String content){
-        //Abusing mix:title as its registered by default
+        //Abusing mix:title as it's registered by default
         nb.child(fileName).setProperty(JCR_MIXINTYPES, Collections.singleton("mix:title"), Type.NAMES)
                 .child("jcr:content").setProperty("jcr:data", content.getBytes());
     }
@@ -375,7 +371,7 @@ public class AggregateTest {
     //~---------------------------------< Prop Includes >
 
     @Test
-    public void propOneLevelNamed() throws Exception{
+    public void propOneLevelNamed() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         rules.child("nt:folder");
         child(rules, "nt:folder/properties/p1")
@@ -395,7 +391,7 @@ public class AggregateTest {
     }
 
     @Test
-    public void propOneLevelRegex() throws Exception{
+    public void propOneLevelRegex() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         rules.child("nt:folder");
         child(rules, "nt:folder/properties/p1")
@@ -416,10 +412,33 @@ public class AggregateTest {
         assertThat(col.getPropPaths(), hasItems("a/foo1", "a/foo2"));
     }
 
+    @Test
+    public void regexWithHiddenElements() {
+        NodeBuilder rules = builder.child(INDEX_RULES);
+        rules.child("nt:folder");
+        child(rules, "nt:folder/properties/p1")
+                .setProperty(FulltextIndexConstants.PROP_NAME, "a/.*")
+                .setProperty(FulltextIndexConstants.PROP_IS_REGEX, true);
+
+        IndexDefinition defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
+        Aggregate ag = defn.getApplicableIndexingRule("nt:folder").getAggregate();
+
+        NodeBuilder nb = newNode("nt:folder");
+        nb.child("a").setProperty("foo1", "foo");
+        nb.child("a").setProperty("foo2", "foo");
+        nb.child("a").setProperty(":hiddenProperty", "foo");
+        nb.child("b").setProperty("p2", "foo");
+        nb.child("a").child(":hiddenNode").setProperty("foo3", "foo");
+
+        ag.collectAggregates(nb.getNodeState(), col);
+        assertEquals(2, col.getPropPaths().size());
+        assertThat(col.getPropPaths(), hasItems("a/foo1", "a/foo2"));
+    }
+
     //~---------------------------------< IndexingConfig >
 
     @Test
-    public void simpleAggregateConfig() throws Exception{
+    public void simpleAggregateConfig() {
         NodeBuilder aggregates = builder.child(FulltextIndexConstants.AGGREGATES);
         NodeBuilder aggFolder = aggregates.child("nt:folder");
         aggFolder.child("i1").setProperty(FulltextIndexConstants.AGG_PATH, "*");
@@ -431,7 +450,7 @@ public class AggregateTest {
     }
 
     @Test
-    public void aggregateConfig2() throws Exception{
+    public void aggregateConfig2() {
         NodeBuilder aggregates = builder.child(FulltextIndexConstants.AGGREGATES);
         NodeBuilder aggFolder = aggregates.child("nt:folder");
         aggFolder.setProperty(FulltextIndexConstants.AGG_RECURSIVE_LIMIT, 42);
@@ -455,7 +474,7 @@ public class AggregateTest {
     }
 
     private static NodeBuilder child(NodeBuilder nb, String path) {
-        for (String name : PathUtils.elements(checkNotNull(path))) {
+        for (String name : PathUtils.elements(Objects.requireNonNull(path))) {
             nb = nb.child(name);
         }
         return nb;
@@ -471,7 +490,7 @@ public class AggregateTest {
 
     private static class TestCollector implements Aggregate.ResultCollector {
         final ListMultimap<String, NodeIncludeResult> nodeResults = ArrayListMultimap.create();
-        final Map<String, PropertyIncludeResult> propResults = newHashMap();
+        final Map<String, PropertyIncludeResult> propResults = new HashMap<>();
         @Override
         public void onResult(NodeIncludeResult result) {
             nodeResults.put(result.nodePath, result);
@@ -497,7 +516,7 @@ public class AggregateTest {
         }
 
         public List<NodeIncludeResult> getRelativeNodeResults(String path, String rootIncludePath){
-            List<NodeIncludeResult> result = Lists.newArrayList();
+            List<NodeIncludeResult> result = new ArrayList<>();
 
             for (NodeIncludeResult nr : nodeResults.get(path)){
                 if (rootIncludePath.equals(nr.rootIncludePath)){
@@ -510,7 +529,7 @@ public class AggregateTest {
     }
 
     private static class SimpleMapper implements Aggregate.AggregateMapper {
-        final Map<String, Aggregate> mapping = newHashMap();
+        final Map<String, Aggregate> mapping = new HashMap<>();
 
         @Override
         public Aggregate getAggregate(String nodeTypeName) {