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 2020/10/14 07:52:43 UTC

svn commit: r1882476 - in /jackrabbit/oak/trunk: oak-core/src/test/java/org/apache/jackrabbit/oak/query/ oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/ oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dy...

Author: fortino
Date: Wed Oct 14 07:52:43 2020
New Revision: 1882476

URL: http://svn.apache.org/viewvc?rev=1882476&view=rev
Log:
OAK-9211: add support for dynamic boost in elastic

Added:
    jackrabbit/oak/trunk/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticDynamicBoostQueryTest.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneDocumentMaker.java
    jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/DynamicBoostTest.java
    jackrabbit/oak/trunk/oak-search-elastic/pom.xml
    jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticIndexDefinition.java
    jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/index/ElasticDocument.java
    jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/index/ElasticDocumentMaker.java
    jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/index/ElasticIndexHelper.java
    jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/query/ElasticRequestHandler.java
    jackrabbit/oak/trunk/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticAbstractQueryTest.java
    jackrabbit/oak/trunk/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticFullTextAsyncTest.java
    jackrabbit/oak/trunk/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticOrderByTest.java
    jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinition.java
    jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/PropertyDefinition.java
    jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextDocumentMaker.java

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java?rev=1882476&r1=1882475&r2=1882476&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java Wed Oct 14 07:52:43 2020
@@ -119,7 +119,7 @@ public abstract class AbstractQueryTest
     }
 
     protected Result executeQuery(String statement, String language,
-            Map<String, PropertyValue> sv) throws ParseException {
+                                  Map<String, PropertyValue> sv) throws ParseException {
         return qe.executeQuery(statement, language, sv, NO_MAPPINGS);
     }
 
@@ -272,9 +272,7 @@ public abstract class AbstractQueryTest
             if (!query.contains("order by") && !skipSort) {
                 Collections.sort(lines);
             }
-        } catch (ParseException e) {
-            lines.add(e.toString());
-        } catch (IllegalArgumentException e) {
+        } catch (ParseException | IllegalArgumentException e) {
             lines.add(e.toString());
         }
         time = System.currentTimeMillis() - time;
@@ -307,7 +305,7 @@ public abstract class AbstractQueryTest
     }
 
     protected List<String> assertQuery(String sql, String language,
-            List<String> expected) {
+                                       List<String> expected) {
         return assertQuery(sql, language, expected, false);
     }
 
@@ -322,7 +320,7 @@ public abstract class AbstractQueryTest
     protected static void assertResult(@NotNull List<String> expected, @NotNull List<String> actual) {
         for (String p : checkNotNull(expected)) {
             assertTrue("Expected path " + p + " not found, got " + actual, checkNotNull(actual)
-                .contains(p));
+                    .contains(p));
         }
         assertEquals("Result set size is different: " + actual, expected.size(),
                 actual.size());
@@ -371,7 +369,7 @@ public abstract class AbstractQueryTest
 
     /**
      * Check whether the test is running in debug mode.
-     * 
+     *
      * @return true if debug most is (most likely) enabled
      */
     protected static boolean isDebugModeEnabled() {
@@ -414,7 +412,7 @@ public abstract class AbstractQueryTest
         } else {
             throw new UnsupportedOperationException(
                     "Unsupported " + (char) tokenizer.read()
-                    + ". This should be either '+' or '-'.");
+                            + ". This should be either '+' or '-'.");
         }
     }
 
@@ -526,7 +524,7 @@ public abstract class AbstractQueryTest
         }
         return createProperty(name, values, Type.fromTag(type, true));
     }
-    
+
     static String formatSQL(String sql) {
         int start = 0;
         while (true) {
@@ -539,7 +537,7 @@ public abstract class AbstractQueryTest
             sql = sql.trim();
             start = index + 7;
         }
-        
+
         // the "(?s)" is enabling the "dot all" flag
         // keep /* xpath ... */ to ensure the xpath comment
         // is really there (and at the right position)
@@ -554,7 +552,7 @@ public abstract class AbstractQueryTest
         sql = sql.replaceAll(" order by ", "\n  order by ");
         return sql;
     }
-    
+
     static String formatPlan(String plan) {
         plan = plan.replaceAll(" where ", "\n  where ");
         plan = plan.replaceAll(" inner join ", "\n  inner join ");
@@ -562,23 +560,23 @@ public abstract class AbstractQueryTest
         plan = plan.replaceAll(" and ", "\n  and ");
         return plan;
     }
-    
+
     /**
      * A line reader that supports multi-line statements, where lines that start
      * with a space belong to the previous line.
      */
     class ContinueLineReader {
-        
+
         private final LineNumberReader reader;
-        
+
         ContinueLineReader(LineNumberReader reader) {
             this.reader = reader;
         }
-        
+
         public void close() throws IOException {
             reader.close();
         }
-        
+
         public String readLine() throws IOException {
             String line = reader.readLine();
             if (line == null || line.trim().length() == 0) {

Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneDocumentMaker.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneDocumentMaker.java?rev=1882476&r1=1882475&r2=1882476&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneDocumentMaker.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneDocumentMaker.java Wed Oct 14 07:52:43 2020
@@ -55,8 +55,6 @@ import static org.apache.jackrabbit.oak.
 public class LuceneDocumentMaker extends FulltextDocumentMaker<Document> {
     private static final Logger log = LoggerFactory.getLogger(LuceneDocumentMaker.class);
 
-    private static final String DYNAMIC_BOOST_TAG_NAME = "name";
-    private static final String DYNAMIC_BOOST_TAG_CONFIDENCE = "confidence";
     private static final String DYNAMIC_BOOST_SPLIT_REGEX = "[:/]";
 
     private final FacetsConfigProvider facetsConfigProvider;
@@ -314,7 +312,7 @@ public class LuceneDocumentMaker extends
     }
 
     @Override
-    protected void indexSimilarityStrings(Document doc, PropertyDefinition pd, String value) throws IOException {
+    protected void indexSimilarityStrings(Document doc, PropertyDefinition pd, String value) {
         for (Field f : FieldFactory.newSimilarityFields(pd.name, value)) {
             doc.add(f);
         }
@@ -338,71 +336,41 @@ public class LuceneDocumentMaker extends
     }
 
     @Override
-    protected boolean indexDynamicBoost(Document doc, PropertyDefinition pd, NodeState nodeState, String propertyName) {
-        NodeState propertNode = nodeState;
-        String parentName = PathUtils.getParentPath(propertyName);
-        for (String c : PathUtils.elements(parentName)) {
-            propertNode = propertNode.getChildNode(c);
+    protected boolean indexDynamicBoost(Document doc, String parent, String nodeName, String value, double confidence) {
+        List<String> tokens = new ArrayList<>(splitForIndexing(value));
+        if (tokens.size() > 1) {
+            // Actual name not in tokens
+            tokens.add(value);
         }
         boolean added = false;
-        for (String nodeName : propertNode.getChildNodeNames()) {
-            NodeState dynaTag = propertNode.getChildNode(nodeName);
-            PropertyState p = dynaTag.getProperty(DYNAMIC_BOOST_TAG_NAME);
-            if (p == null) {
-                // here we don't log a warning, because possibly it will be added later
-                continue;
-            }
-            if (p.isArray()) {
-                log.warn(p.getName() + " is an array: {}", parentName);
-                continue;
-            }
-            String dynaTagName = p.getValue(Type.STRING);
-            p = dynaTag.getProperty(DYNAMIC_BOOST_TAG_CONFIDENCE);
-            if (p == null) {
-                // here we don't log a warning, because possibly it will be added later
-                continue;
-            }
-            if (p.isArray()) {
-                log.warn(p.getName() + " is an array: {}", parentName);
-                continue;
-            }
-            double dynaTagConfidence;
-            try {
-                dynaTagConfidence = p.getValue(Type.DOUBLE);
-            } catch (NumberFormatException e) {
-                log.warn(p.getName() + " parsing failed: {}", parentName, e);
-                continue;
-            }
-            if (!Double.isFinite(dynaTagConfidence)) {
-                log.warn(p.getName() + " is not finite: {}", parentName);
-                continue;
-            }
-            List<String> tokens = new ArrayList<>(splitForIndexing(dynaTagName));
-            if (tokens.size() > 1) {
-                // Actual name not in tokens
-                tokens.add(dynaTagName);
-            }
-            boolean addedForThisChild = false;
-            for (String token : tokens) {
-                if (token.length() > 0) {
-                    AugmentedField f = new AugmentedField(parentName + "/" + token.toLowerCase(), dynaTagConfidence);
-                    if (doc.getField(f.name()) == null) {
-                        addedForThisChild = true;
-                        added = true;
-                        doc.add(f);
-                    }
+        for (String token : tokens) {
+            if (token.length() > 0) {
+                AugmentedField f = new AugmentedField(parent + "/" + token.toLowerCase(), confidence);
+                if (doc.getField(f.name()) == null) {
+                    doc.add(f);
+                    added = true;
                 }
             }
-            if (addedForThisChild) {
-                log.trace(
-                        "Added augmented fields: {}[{}], {}",
-                        parentName + "/", String.join(", ", tokens), dynaTagConfidence
-                );
-            }
         }
+
+        if (added) {
+            log.trace(
+                    "Added augmented fields: {}[{}], {}",
+                    parent + "/", String.join(", ", tokens), confidence
+            );
+        }
+
         return added;
     }
 
+    private static List<String> splitForIndexing(String tagName) {
+        return Arrays.asList(removeBackSlashes(tagName).split(DYNAMIC_BOOST_SPLIT_REGEX));
+    }
+
+    private static String removeBackSlashes(String text) {
+        return text.replaceAll("\\\\", "");
+    }
+
     private static class AugmentedField extends Field {
         private static final FieldType ft = new FieldType();
         static {
@@ -420,12 +388,4 @@ public class LuceneDocumentMaker extends
         }
     }
 
-    private static List<String> splitForIndexing(String tagName) {
-        return Arrays.asList(removeBackSlashes(tagName).split(DYNAMIC_BOOST_SPLIT_REGEX));
-    }
-
-    private static String removeBackSlashes(String text) {
-        return text.replaceAll("\\\\", "");
-    }
-
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/DynamicBoostTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/DynamicBoostTest.java?rev=1882476&r1=1882475&r2=1882476&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/DynamicBoostTest.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/DynamicBoostTest.java Wed Oct 14 07:52:43 2020
@@ -60,9 +60,9 @@ public class DynamicBoostTest extends Ab
 
     public static final String ASSET_NODE_TYPE =
             "[dam:Asset]\n" +
-            " - * (UNDEFINED) multiple\n" +
-            " - * (UNDEFINED)\n" +
-            " + * (nt:base) = oak:TestNode VERSION";
+                    " - * (UNDEFINED) multiple\n" +
+                    " - * (UNDEFINED)\n" +
+                    " + * (nt:base) = oak:TestNode VERSION";
 
     private static final String UNSTRUCTURED = "nt:unstructured";
 
@@ -77,16 +77,16 @@ public class DynamicBoostTest extends Ab
     protected ContentRepository createRepository() {
         IndexTracker tracker = new IndexTracker();
         LuceneIndexEditorProvider editorProvider = new LuceneIndexEditorProvider(null,
-            new ExtractedTextCache(0, 0),
-            factory, Mounts.defaultMountInfoProvider());
+                new ExtractedTextCache(0, 0),
+                factory, Mounts.defaultMountInfoProvider());
         LuceneIndexProvider provider = new LuceneIndexProvider(tracker,
-            factory);
+                factory);
         return new Oak()
-            .with(new OpenSecurityProvider())
-            .with((QueryIndexProvider) provider)
-            .with((Observer) provider)
-            .with(editorProvider)
-            .createContentRepository();
+                .with(new OpenSecurityProvider())
+                .with((QueryIndexProvider) provider)
+                .with((Observer) provider)
+                .with(editorProvider)
+                .createContentRepository();
     }
 
     @Test public void withFieldProvider() throws Exception {
@@ -98,8 +98,8 @@ public class DynamicBoostTest extends Ab
         String log = runTest(IndexFieldProviderImpl.class, true);
         assertEquals(
                 "[" +
-                "Added augmented fields: jcr:content/metadata/predictedTags/[my, a, my:a], 10.0" +
-                "]", log);
+                        "Added augmented fields: jcr:content/metadata/predictedTags/[my, a, my:a], 10.0" +
+                        "]", log);
     }
 
     @Test public void withDynamicBoost() throws Exception {
@@ -115,17 +115,17 @@ public class DynamicBoostTest extends Ab
         String log = runTest(LuceneDocumentMaker.class, true);
         assertEquals(
                 "[" +
-                "Added augmented fields: jcr:content/metadata/predictedTags/[my, a, my:a], 10.0, " +
-                "Added augmented fields: jcr:content/metadata/predictedTags/[my, a, my:a], 30.0, " +
-                "confidence is not finite: jcr:content/metadata/predictedTags, " +
-                "confidence is not finite: jcr:content/metadata/predictedTags, " +
-                "confidence parsing failed: jcr:content/metadata/predictedTags, " +
-                "confidence parsing failed: jcr:content/metadata/predictedTags, " +
-                "confidence is an array: jcr:content/metadata/predictedTags, " +
-                "confidence is an array: jcr:content/metadata/predictedTags, " +
-                "name is an array: jcr:content/metadata/predictedTags, " +
-                "name is an array: jcr:content/metadata/predictedTags" +
-                "]", log);
+                        "Added augmented fields: jcr:content/metadata/predictedTags/[my, a, my:a], 10.0, " +
+                        "Added augmented fields: jcr:content/metadata/predictedTags/[my, a, my:a], 30.0, " +
+                        "confidence is not finite: jcr:content/metadata/predictedTags, " +
+                        "confidence is not finite: jcr:content/metadata/predictedTags, " +
+                        "confidence parsing failed: jcr:content/metadata/predictedTags, " +
+                        "confidence parsing failed: jcr:content/metadata/predictedTags, " +
+                        "confidence is an array: jcr:content/metadata/predictedTags, " +
+                        "confidence is an array: jcr:content/metadata/predictedTags, " +
+                        "name is an array: jcr:content/metadata/predictedTags, " +
+                        "name is an array: jcr:content/metadata/predictedTags" +
+                        "]", log);
     }
 
     @Test public void withDynamicBoostMissingProperty() throws Exception {
@@ -152,10 +152,10 @@ public class DynamicBoostTest extends Ab
             Tree node = createNodeWithType(test, "item", "dam:Asset");
             Tree predicted =
                     createNodeWithType(
-                    createNodeWithType(
-                    createNodeWithType(node, JcrConstants.JCR_CONTENT, UNSTRUCTURED),
-                    "metadata", UNSTRUCTURED),
-                    "predictedTags", UNSTRUCTURED);
+                            createNodeWithType(
+                                    createNodeWithType(node, JcrConstants.JCR_CONTENT, UNSTRUCTURED),
+                                    "metadata", UNSTRUCTURED),
+                            "predictedTags", UNSTRUCTURED);
             Tree t = createNodeWithType(predicted, "a", UNSTRUCTURED);
             if (nameProperty) {
                 t.setProperty("name", "my:a");

Modified: jackrabbit/oak/trunk/oak-search-elastic/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search-elastic/pom.xml?rev=1882476&r1=1882475&r2=1882476&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search-elastic/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-search-elastic/pom.xml Wed Oct 14 07:52:43 2020
@@ -250,7 +250,7 @@
     <dependency>
       <groupId>org.testcontainers</groupId>
       <artifactId>elasticsearch</artifactId>
-      <version>1.12.5</version>
+      <version>1.14.3</version>
       <scope>test</scope>
     </dependency>
     <dependency>

Modified: jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticIndexDefinition.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticIndexDefinition.java?rev=1882476&r1=1882475&r2=1882476&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticIndexDefinition.java (original)
+++ jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticIndexDefinition.java Wed Oct 14 07:52:43 2020
@@ -84,6 +84,7 @@ public class ElasticIndexDefinition exte
     private final String remoteAlias;
 
     private final Map<String, List<PropertyDefinition>> propertiesByName;
+    private final List<PropertyDefinition> dynamicBoostProperties;
 
     public ElasticIndexDefinition(NodeState root, NodeState defn, String indexPath, String indexPrefix) {
         super(root, defn, determineIndexFormatVersion(defn), determineUniqueId(defn), indexPath);
@@ -99,6 +100,12 @@ public class ElasticIndexDefinition exte
                 .flatMap(rule -> StreamSupport.stream(rule.getProperties().spliterator(), false))
                 .filter(pd -> pd.index) // keep only properties that can be indexed
                 .collect(Collectors.groupingBy(pd -> pd.name));
+
+        this.dynamicBoostProperties = getDefinedRules()
+                .stream()
+                .flatMap(IndexingRule::getNamePatternsProperties)
+                .filter(pd -> pd.dynamicBoost)
+                .collect(Collectors.toList());
     }
 
     /**
@@ -114,6 +121,10 @@ public class ElasticIndexDefinition exte
         return propertiesByName;
     }
 
+    public List<PropertyDefinition> getDynamicBoostProperties() {
+        return dynamicBoostProperties;
+    }
+
     /**
      * Returns the keyword field name mapped in Elasticsearch for the specified property name.
      * @param propertyName the property name in the index rules

Modified: jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/index/ElasticDocument.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/index/ElasticDocument.java?rev=1882476&r1=1882475&r2=1882476&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/index/ElasticDocument.java (original)
+++ jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/index/ElasticDocument.java Wed Oct 14 07:52:43 2020
@@ -41,6 +41,7 @@ class ElasticDocument {
     private final List<String> notNullProps;
     private final List<String> nullProps;
     private final Map<String, Object> properties;
+    private final Map<String, Map<String, Double>> dynamicBoostFields;
 
     ElasticDocument(String path) {
         this.path = path;
@@ -49,6 +50,7 @@ class ElasticDocument {
         this.notNullProps = new ArrayList<>();
         this.nullProps = new ArrayList<>();
         this.properties = new HashMap<>();
+        this.dynamicBoostFields = new HashMap<>();
     }
 
     void addFulltext(String value) {
@@ -87,6 +89,11 @@ class ElasticDocument {
         addProperty(FieldNames.PATH_DEPTH, depth);
     }
 
+    void addDynamicBoostField(String propName, String value, double boost) {
+        dynamicBoostFields.computeIfAbsent(propName, s -> new HashMap<>())
+                .putIfAbsent(value, boost);
+    }
+
     public String build() {
         String ret;
         try {
@@ -99,7 +106,7 @@ class ElasticDocument {
                 }
                 if (suggest.size() > 0) {
                     builder.startArray(FieldNames.SUGGEST);
-                    for(String val: suggest) {
+                    for (String val : suggest) {
                         builder.startObject().field("value", val).endObject();
                     }
                     builder.endArray();
@@ -113,6 +120,16 @@ class ElasticDocument {
                 for (Map.Entry<String, Object> prop : properties.entrySet()) {
                     builder.field(prop.getKey(), prop.getValue());
                 }
+                for (Map.Entry<String, Map<String, Double>> f : dynamicBoostFields.entrySet()) {
+                    builder.startArray(f.getKey());
+                    for (Map.Entry<String, Double> v : f.getValue().entrySet()) {
+                        builder.startObject();
+                        builder.field("value", v.getKey());
+                        builder.field("boost", v.getValue());
+                        builder.endObject();
+                    }
+                    builder.endArray();
+                }
             }
             builder.endObject();
 

Modified: jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/index/ElasticDocumentMaker.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/index/ElasticDocumentMaker.java?rev=1882476&r1=1882475&r2=1882476&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/index/ElasticDocumentMaker.java (original)
+++ jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/index/ElasticDocumentMaker.java Wed Oct 14 07:52:43 2020
@@ -195,9 +195,11 @@ class ElasticDocumentMaker extends Fullt
     }
 
     @Override
-    protected boolean indexDynamicBoost(ElasticDocument doc, PropertyDefinition pd, NodeState nodeState,
-                                        String propertyName) {
-        // TODO : not implemented
+    protected boolean indexDynamicBoost(ElasticDocument doc, String parent, String nodeName, String token, double boost) {
+        if (token.length() > 0) {
+            doc.addDynamicBoostField(nodeName, token, boost);
+            return true;
+        }
         return false;
     }
 }

Modified: jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/index/ElasticIndexHelper.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/index/ElasticIndexHelper.java?rev=1882476&r1=1882475&r2=1882476&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/index/ElasticIndexHelper.java (original)
+++ jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/index/ElasticIndexHelper.java Wed Oct 14 07:52:43 2020
@@ -220,6 +220,25 @@ class ElasticIndexHelper {
             }
             mappingBuilder.endObject();
         }
+
+        for (PropertyDefinition pd : indexDefinition.getDynamicBoostProperties()) {
+            mappingBuilder.startObject(pd.nodeName);
+            {
+                mappingBuilder.field("type", "nested");
+                mappingBuilder.startObject("properties");
+                {
+                    mappingBuilder.startObject("value")
+                            .field("type", "text")
+                            .field("analyzer", "oak_analyzer")
+                            .endObject();
+                    mappingBuilder.startObject("boost")
+                            .field("type", "double")
+                            .endObject();
+                }
+                mappingBuilder.endObject();
+            }
+            mappingBuilder.endObject();
+        }
     }
 
     // we need to check if in the defined rules there are properties with the same name and different types

Modified: jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/query/ElasticRequestHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/query/ElasticRequestHandler.java?rev=1882476&r1=1882475&r2=1882476&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/query/ElasticRequestHandler.java (original)
+++ jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/query/ElasticRequestHandler.java Wed Oct 14 07:52:43 2020
@@ -50,6 +50,7 @@ import org.elasticsearch.index.query.Nes
 import org.elasticsearch.index.query.Operator;
 import org.elasticsearch.index.query.QueryBuilder;
 import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
 import org.elasticsearch.index.search.MatchQuery;
 import org.elasticsearch.search.aggregations.AggregationBuilders;
 import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
@@ -95,6 +96,7 @@ import static org.apache.jackrabbit.oak.
 import static org.apache.jackrabbit.util.ISO8601.parse;
 import static org.elasticsearch.index.query.MoreLikeThisQueryBuilder.Item;
 import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
+import static org.elasticsearch.index.query.QueryBuilders.functionScoreQuery;
 import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
 import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
 import static org.elasticsearch.index.query.QueryBuilders.multiMatchQuery;
@@ -422,15 +424,21 @@ public class ElasticRequestHandler {
             }
 
             private boolean visitTerm(String propertyName, String text, String boost, boolean not) {
-                QueryBuilder q = fullTextQuery(text, getElasticFieldName(propertyName), pr);
+                // base query
+                QueryBuilder fullTextQuery = fullTextQuery(text, getElasticFieldName(propertyName), pr);
                 if (boost != null) {
-                    q.boost(Float.parseFloat(boost));
+                    fullTextQuery.boost(Float.parseFloat(boost));
                 }
+                BoolQueryBuilder boolQueryBuilder = boolQuery().must(fullTextQuery);
+                // add dynamic boosts in SHOULD if available
+                Stream<QueryBuilder> dynamicScoreQueries = dynamicScoreQueries(text);
+                dynamicScoreQueries.forEach(boolQueryBuilder::should);
+
                 if (not) {
-                    BoolQueryBuilder bq = boolQuery().mustNot(q);
+                    BoolQueryBuilder bq = boolQuery().mustNot(boolQueryBuilder);
                     result.set(bq);
                 } else {
-                    result.set(q);
+                    result.set(boolQueryBuilder);
                 }
                 return true;
             }
@@ -438,6 +446,12 @@ public class ElasticRequestHandler {
         return result.get();
     }
 
+    private Stream<QueryBuilder> dynamicScoreQueries(String text) {
+        return elasticIndexDefinition.getDynamicBoostProperties().stream()
+                .map(pd -> nestedQuery(pd.nodeName, functionScoreQuery(matchQuery(pd.nodeName + ".value", text),
+                        ScoreFunctionBuilders.fieldValueFactorFunction(pd.nodeName + ".boost")), ScoreMode.Avg));
+    }
+
     private List<QueryBuilder> nonFullTextConstraints(IndexPlan plan, PlanResult planResult) {
         final BiPredicate<Iterable<String>, String> any = (iterable, value) ->
                 StreamSupport.stream(iterable.spliterator(), false).anyMatch(value::equals);
@@ -634,6 +648,7 @@ public class ElasticRequestHandler {
         } else {
             return matchQuery(fieldName, text).operator(Operator.AND);
         }
+
     }
 
     private QueryBuilder createQuery(String propertyName, Filter.PropertyRestriction pr,

Modified: jackrabbit/oak/trunk/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticAbstractQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticAbstractQueryTest.java?rev=1882476&r1=1882475&r2=1882476&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticAbstractQueryTest.java (original)
+++ jackrabbit/oak/trunk/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticAbstractQueryTest.java Wed Oct 14 07:52:43 2020
@@ -50,12 +50,14 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
+import java.util.List;
 import java.util.concurrent.TimeUnit;
 
 import static com.google.common.collect.Lists.newArrayList;
 import static org.apache.jackrabbit.oak.plugins.index.CompositeIndexEditorProvider.compose;
 import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NAME;
 import static org.apache.jackrabbit.oak.plugins.index.elastic.ElasticIndexDefinition.BULK_FLUSH_INTERVAL_MS_DEFAULT;
+import static org.junit.Assert.assertEquals;
 
 public abstract class ElasticAbstractQueryTest extends AbstractQueryTest {
 
@@ -176,15 +178,15 @@ public abstract class ElasticAbstractQue
     }
 
     protected IndexDefinitionBuilder createIndex(String... propNames) {
-        return createIndex(true, propNames);
+        return createIndex(true, "nt:base", propNames);
     }
 
-    protected IndexDefinitionBuilder createIndex(boolean isPropertyIndex, String... propNames) {
+    protected IndexDefinitionBuilder createIndex(boolean isPropertyIndex, String nodeType, String... propNames) {
         IndexDefinitionBuilder builder = new ElasticIndexDefinitionBuilder();
         if (!useAsyncIndexing()) {
             builder = builder.noAsync();
         }
-        IndexDefinitionBuilder.IndexRule indexRule = builder.indexRule("nt:base");
+        IndexDefinitionBuilder.IndexRule indexRule = builder.indexRule(nodeType);
         if (isPropertyIndex) {
             for (String propName : propNames) {
                 indexRule.property(propName).propertyIndex();
@@ -243,4 +245,9 @@ public abstract class ElasticAbstractQue
                 esConnection.getIndexPrefix());
     }
 
+    protected void assertOrderedQuery(String sql, List<String> paths) {
+        List<String> result = executeQuery(sql, AbstractQueryTest.SQL2, true, true);
+        assertEquals(paths, result);
+    }
+
 }

Added: jackrabbit/oak/trunk/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticDynamicBoostQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticDynamicBoostQueryTest.java?rev=1882476&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticDynamicBoostQueryTest.java (added)
+++ jackrabbit/oak/trunk/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticDynamicBoostQueryTest.java Wed Oct 14 07:52:43 2020
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.jackrabbit.oak.plugins.index.elastic;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.plugins.index.search.util.IndexDefinitionBuilder;
+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;
+
+import static org.apache.jackrabbit.JcrConstants.NT_UNSTRUCTURED;
+
+public class ElasticDynamicBoostQueryTest extends ElasticAbstractQueryTest {
+
+    public static final String ASSET_NODE_TYPE =
+            "[dam:Asset]\n" +
+                    " - * (UNDEFINED) multiple\n" +
+                    " - * (UNDEFINED)\n" +
+                    " + * (nt:base) = oak:TestNode VERSION";
+
+    @Test
+    public void dynamicBoost() throws CommitFailedException {
+        configureIndex();
+
+        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 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);
+        root.commit();
+
+        assertEventually(() -> {
+            assertQuery("//element(*, dam:Asset)[jcr:contains(@title, 'flower')]",
+                    XPATH, Arrays.asList("/test/item1", "/test/item2"));
+            assertOrderedQuery("select [jcr:path] from [dam:Asset] where contains(title, 'red flower')",
+                    Arrays.asList("/test/item1", "/test/item2"));
+            assertOrderedQuery("select [jcr:path] from [dam:Asset] where contains(title, 'blue flower')",
+                    Arrays.asList("/test/item2", "/test/item1"));
+        });
+    }
+
+    @Test
+    public void dynamicBoostAnalyzed() throws CommitFailedException {
+        configureIndex();
+
+        Tree test = createNodeWithType(root.getTree("/"), "test", NT_UNSTRUCTURED);
+        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);
+        Tree item1Color2 = createNodeWithType(item1Metadata,"color2", NT_UNSTRUCTURED);
+        item1Color2.setProperty("name", "blue");
+        item1Color2.setProperty("confidence", 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);
+        root.commit();
+
+        assertEventually(() -> {
+            assertQuery("//element(*, dam:Asset)[jcr:contains(@title, 'flower')]",
+                    XPATH, Arrays.asList("/test/item1", "/test/item2"));
+            assertOrderedQuery("select [jcr:path] from [dam:Asset] where contains(title, 'red-flower')",
+                    Arrays.asList("/test/item1", "/test/item2"));
+            assertOrderedQuery("select [jcr:path] from [dam:Asset] where contains(title, 'blue-flower')",
+                    Arrays.asList("/test/item2", "/test/item1"));
+        });
+    }
+
+    private void configureIndex() throws CommitFailedException {
+        NodeTypeRegistry.register(root, toInputStream(ASSET_NODE_TYPE), "test nodeType");
+        IndexDefinitionBuilder builder = createIndex(true, "dam:Asset", "title", "dynamicBoost");
+        IndexDefinitionBuilder.PropertyRule title = builder.indexRule("dam:Asset")
+                .property("title")
+                .analyzed();
+        title.getBuilderTree().setProperty(JcrConstants.JCR_PRIMARYTYPE, NT_UNSTRUCTURED, Type.NAME);
+        IndexDefinitionBuilder.PropertyRule db = builder.indexRule("dam:Asset").property("dynamicBoost");
+        Tree dbTree = db.getBuilderTree();
+        dbTree.setProperty(JcrConstants.JCR_PRIMARYTYPE, NT_UNSTRUCTURED, Type.NAME);
+        dbTree.setProperty("name", "jcr:content/metadata/.*");
+        dbTree.setProperty("isRegexp", true);
+        dbTree.setProperty("dynamicBoost", true);
+        setIndex("damAsset_" + UUID.randomUUID(), builder);
+        root.commit();
+    }
+
+    private Tree createNodeWithMetadata(Tree parent, String nodeName, String title) {
+        Tree item = createNodeWithType(parent, nodeName, "dam:Asset");
+        item.setProperty("title", title);
+
+        return createNodeWithType(
+                createNodeWithType(item, JcrConstants.JCR_CONTENT, NT_UNSTRUCTURED),
+                "metadata", NT_UNSTRUCTURED);
+    }
+
+    private static 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());
+    }
+}

Modified: jackrabbit/oak/trunk/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticFullTextAsyncTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticFullTextAsyncTest.java?rev=1882476&r1=1882475&r2=1882476&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticFullTextAsyncTest.java (original)
+++ jackrabbit/oak/trunk/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticFullTextAsyncTest.java Wed Oct 14 07:52:43 2020
@@ -118,7 +118,7 @@ public class ElasticFullTextAsyncTest ex
      */
     @Test
     public void onlyNodeScopeIndexedQuery() throws Exception {
-        IndexDefinitionBuilder builder = createIndex(false, "a", "b").async("async");
+        IndexDefinitionBuilder builder = createIndex(false, "nt:base", "a", "b").async("async");
         builder.indexRule("nt:base").property("a").nodeScopeIndex();
         builder.indexRule("nt:base").property("b").nodeScopeIndex();
 
@@ -176,7 +176,7 @@ public class ElasticFullTextAsyncTest ex
      */
     @Test
     public void onlyAnalyzedPropertyShouldNotBeReturnedForNodeScopeIndexedQuery() throws Exception {
-        IndexDefinitionBuilder builder = createIndex(false, "a", "b").async("async");
+        IndexDefinitionBuilder builder = createIndex(false, "nt:base", "a", "b").async("async");
         builder.indexRule("nt:base").property("a").nodeScopeIndex();
         builder.indexRule("nt:base").property("b").analyzed();
 

Modified: jackrabbit/oak/trunk/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticOrderByTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticOrderByTest.java?rev=1882476&r1=1882475&r2=1882476&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticOrderByTest.java (original)
+++ jackrabbit/oak/trunk/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/ElasticOrderByTest.java Wed Oct 14 07:52:43 2020
@@ -18,16 +18,13 @@ package org.apache.jackrabbit.oak.plugin
 
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.plugins.index.search.util.IndexDefinitionBuilder;
-import org.apache.jackrabbit.oak.query.AbstractQueryTest;
 import org.junit.Test;
 
 import javax.jcr.PropertyType;
 import java.util.Collections;
-import java.util.List;
 import java.util.UUID;
 
 import static java.util.Arrays.asList;
-import static org.junit.Assert.assertEquals;
 
 public class ElasticOrderByTest extends ElasticAbstractQueryTest {
 
@@ -167,9 +164,4 @@ public class ElasticOrderByTest extends
         assertOrderedQuery("select [jcr:path] from [nt:base] order by @bar DESC, @foo DESC",
                 asList("/test/b", "/test/a2", "/test/a1"));
     }
-
-    private void assertOrderedQuery(String sql, List<String> paths) {
-        List<String> result = executeQuery(sql, AbstractQueryTest.SQL2, true, true);
-        assertEquals(paths, result);
-    }
 }

Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinition.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinition.java?rev=1882476&r1=1882475&r2=1882476&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinition.java (original)
+++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinition.java Wed Oct 14 07:52:43 2020
@@ -29,6 +29,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 import java.util.regex.Pattern;
+import java.util.stream.Stream;
 
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
@@ -175,7 +176,7 @@ public class IndexDefinition implements
      * native sort order
      */
     public static final OrderEntry NATIVE_SORT_ORDER = new OrderEntry(JCR_SCORE, Type.UNDEFINED,
-        OrderEntry.Order.DESCENDING);
+            OrderEntry.Order.DESCENDING);
 
     protected final boolean fullTextEnabled;
 
@@ -919,6 +920,9 @@ public class IndexDefinition implements
          * Case insensitive map of lower cased propertyName to propertyConfigs
          */
         private final Map<String, PropertyDefinition> propConfigs;
+        /**
+         * List of {@code NamePattern}s configured for this rule
+         */
         private final List<NamePattern> namePatterns;
         private final List<PropertyDefinition> nullCheckEnabledProperties;
         private final List<PropertyDefinition> functionRestrictions;
@@ -1065,6 +1069,10 @@ public class IndexDefinition implements
             return similarityProperties;
         }
 
+        public Stream<PropertyDefinition> getNamePatternsProperties() {
+            return namePatterns.stream().map(NamePattern::getConfig);
+        }
+
         @Override
         public String toString() {
             String str = "IndexRule: "+ nodeTypeName;
@@ -1144,7 +1152,7 @@ public class IndexDefinition implements
         }
 
         public boolean includePropertyType(int type){
-           return IndexDefinition.includePropertyType(propertyTypes, type);
+            return IndexDefinition.includePropertyType(propertyTypes, type);
         }
 
         public Aggregate getAggregate() {
@@ -1182,7 +1190,7 @@ public class IndexDefinition implements
 
             if (propNode.exists() && !hasOrderableChildren(propNode)){
                 log.warn("Properties node for [{}] does not have orderable " +
-                    "children in [{}]", this, IndexDefinition.this);
+                        "children in [{}]", this, IndexDefinition.this);
             }
 
             //In case of a pure nodetype index we just index primaryType and mixins
@@ -1247,8 +1255,8 @@ public class IndexDefinition implements
 
                     //Include props with name, boosted and nodeScopeIndex
                     if (pd.nodeScopeIndex
-                        && pd.analyzed
-                        && !pd.isRegexp){
+                            && pd.analyzed
+                            && !pd.isRegexp){
                         nodeScopeAnalyzedProps.add(pd);
                     }
 

Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/PropertyDefinition.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/PropertyDefinition.java?rev=1882476&r1=1882475&r2=1882476&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/PropertyDefinition.java (original)
+++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/PropertyDefinition.java Wed Oct 14 07:52:43 2020
@@ -61,6 +61,8 @@ public class PropertyDefinition {
      */
     public final String name;
 
+    public final String nodeName;
+
     private final int propertyType;
 
     /**
@@ -133,6 +135,7 @@ public class PropertyDefinition {
     public final boolean similarityTags;
 
     public PropertyDefinition(IndexingRule idxDefn, String nodeName, NodeState defn) {
+        this.nodeName = nodeName;
         this.isRegexp = getOptionalValue(defn, PROP_IS_REGEX, false);
         this.name = getName(defn, nodeName);
         this.relative = isRelativeProperty(name);

Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextDocumentMaker.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextDocumentMaker.java?rev=1882476&r1=1882475&r2=1882476&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextDocumentMaker.java (original)
+++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextDocumentMaker.java Wed Oct 14 07:52:43 2020
@@ -61,6 +61,9 @@ public abstract class FulltextDocumentMa
     public static final String WARN_LOG_STRING_SIZE_THRESHOLD_KEY = "oak.repository.property.index.logWarnStringSizeThreshold";
     private static final int DEFAULT_WARN_LOG_STRING_SIZE_THRESHOLD_VALUE = 102400;
 
+    private static final String DYNAMIC_BOOST_TAG_NAME = "name";
+    private static final String DYNAMIC_BOOST_TAG_CONFIDENCE = "confidence";
+
     private final FulltextBinaryTextExtractor textExtractor;
     protected final IndexDefinition definition;
     protected final IndexDefinition.IndexingRule indexingRule;
@@ -101,7 +104,16 @@ public abstract class FulltextDocumentMa
 
     protected abstract void indexTypedProperty(D doc, PropertyState property, String pname, PropertyDefinition pd, int index);
 
-    protected abstract boolean indexDynamicBoost(D doc, PropertyDefinition pd, NodeState nodeState, String propertyName);
+    /**
+     * Indexes a text value that will be used to re-score results with the given confidence
+     * @param doc the full-text document
+     * @param parent the parent node
+     * @param nodeName the current node name
+     * @param value the value to be indexed
+     * @param confidence the confidence (or weight) used for re-scoring
+     * @return {@code true} id the value has been added, otherwise {@code false}
+     */
+    protected abstract boolean indexDynamicBoost(D doc, String parent, String nodeName, String value, double confidence);
 
     protected abstract void indexAncestors(D doc, String path);
 
@@ -122,7 +134,7 @@ public abstract class FulltextDocumentMa
 
     @Nullable
     public D makeDocument(NodeState state) throws IOException {
-        return makeDocument(state, false, Collections.<PropertyState>emptyList());
+        return makeDocument(state, false, Collections.emptyList());
     }
 
     @Nullable
@@ -247,7 +259,7 @@ public abstract class FulltextDocumentMa
             }
             if (pd.dynamicBoost) {
                 try {
-                    dirty |= indexDynamicBoost(doc, pd, state, pname);
+                    dirty |= indexDynamicBoost(doc, pname, pd.nodeName, state);
                 } catch (Exception e) {
                     log.error("Could not index dynamic boost for property {} and definition {}", property, pd, e);
                 }
@@ -624,6 +636,53 @@ public abstract class FulltextDocumentMa
         return dirty;
     }
 
+    protected boolean indexDynamicBoost(D doc, String propertyName, String nodeName, NodeState nodeState) {
+        NodeState propertyNode = nodeState;
+        String parentName = PathUtils.getParentPath(propertyName);
+        for (String c : PathUtils.elements(parentName)) {
+            propertyNode = propertyNode.getChildNode(c);
+        }
+        boolean added = false;
+        for (String childNodeName : propertyNode.getChildNodeNames()) {
+            NodeState dynaTag = propertyNode.getChildNode(childNodeName);
+            PropertyState p = dynaTag.getProperty(DYNAMIC_BOOST_TAG_NAME);
+            if (p == null) {
+                // here we don't log a warning, because possibly it will be added later
+                continue;
+            }
+            if (p.isArray()) {
+                log.warn(p.getName() + " is an array: {}", parentName);
+                continue;
+            }
+            String dynaTagValue = p.getValue(Type.STRING);
+            p = dynaTag.getProperty(DYNAMIC_BOOST_TAG_CONFIDENCE);
+            if (p == null) {
+                // here we don't log a warning, because possibly it will be added later
+                continue;
+            }
+            if (p.isArray()) {
+                log.warn(p.getName() + " is an array: {}", parentName);
+                continue;
+            }
+            double dynaTagConfidence;
+            try {
+                dynaTagConfidence = p.getValue(Type.DOUBLE);
+            } catch (NumberFormatException e) {
+                log.warn(p.getName() + " parsing failed: {}", parentName, e);
+                continue;
+            }
+            if (!Double.isFinite(dynaTagConfidence)) {
+                log.warn(p.getName() + " is not finite: {}", parentName);
+                continue;
+            }
+
+            if (indexDynamicBoost(doc, parentName, nodeName, dynaTagValue, dynaTagConfidence)) {
+                added = true;
+            }
+        }
+        return added;
+    }
+
     protected String getIndexName() {
         return definition.getIndexName();
     }