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 th...@apache.org on 2020/04/22 14:52:47 UTC
svn commit: r1876830 - in /jackrabbit/oak/trunk:
oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/
oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/spi/
oak-lucene/src/test/java/org/apache/jackrabbit/oak/pl...
Author: thomasm
Date: Wed Apr 22 14:52:46 2020
New Revision: 1876830
URL: http://svn.apache.org/viewvc?rev=1876830&view=rev
Log:
OAK-8971 Indexing: dynamic boost, as an alternative to IndexFieldProvider
Added:
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/DynamicBoostTest.java
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/FulltextQueryTermsProviderImpl.java
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/IndexFieldProviderImpl.java
Modified:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneDocumentMaker.java
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/spi/FulltextQueryTermsProvider.java
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/spi/IndexFieldProvider.java
jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elasticsearch/index/ElasticsearchDocumentMaker.java
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/FulltextIndexConstants.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-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=1876830&r1=1876829&r2=1876830&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 Apr 22 14:52:46 2020
@@ -20,6 +20,8 @@
package org.apache.jackrabbit.oak.plugins.index.lucene;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import org.apache.jackrabbit.oak.api.Blob;
@@ -40,7 +42,6 @@ import org.apache.lucene.facet.FacetsCon
import org.apache.lucene.facet.sortedset.SortedSetDocValuesFacetField;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.util.BytesRef;
-import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -54,6 +55,10 @@ 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;
private final IndexAugmentorFactory augmentorFactory;
@@ -331,4 +336,69 @@ 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);
+ }
+ boolean added = false;
+ for (String nodeName : propertNode.getChildNodeNames()) {
+ NodeState dynaTag = propertNode.getChildNode(nodeName);
+ String dynaTagName = dynaTag.getProperty(DYNAMIC_BOOST_TAG_NAME).getValue(Type.STRING);
+ Double dynaTagConfidence = dynaTag.getProperty(DYNAMIC_BOOST_TAG_CONFIDENCE).getValue(Type.DOUBLE);
+
+ 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);
+ }
+ }
+ }
+ if (addedForThisChild) {
+ log.trace(
+ "Added augmented fields: {}[{}], {}",
+ parentName + "/", String.join(", ", tokens), dynaTagConfidence
+ );
+ }
+ }
+ return added;
+ }
+
+ private static class AugmentedField extends Field {
+ private static final FieldType ft = new FieldType();
+ static {
+ ft.setIndexed(true);
+ ft.setStored(false);
+ ft.setTokenized(false);
+ ft.setOmitNorms(false);
+ ft.setIndexOptions(org.apache.lucene.index.FieldInfo.IndexOptions.DOCS_ONLY);
+ ft.freeze();
+ }
+
+ AugmentedField(String name, double weight) {
+ super(name, "1", ft);
+ setBoost((float) weight);
+ }
+ }
+
+ 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/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/spi/FulltextQueryTermsProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/spi/FulltextQueryTermsProvider.java?rev=1876830&r1=1876829&r2=1876830&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/spi/FulltextQueryTermsProvider.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/spi/FulltextQueryTermsProvider.java Wed Apr 22 14:52:46 2020
@@ -24,9 +24,16 @@ import org.jetbrains.annotations.Nullabl
import java.util.Collections;
import java.util.Set;
+
/**
- * Implementations of this interface would get callbacks while forming lucene full text queries.
+ * Implementations of this interface would get callbacks while forming lucene
+ * full text queries.
+ *
+ * @deprecated This interface exposes Lucene API directly - it will be removed
+ * as soon as an alternative is available. See also
+ * IndexFieldProvider.
*/
+@Deprecated
public interface FulltextQueryTermsProvider {
/**
* Implementation which doesn't do anything useful... yet, abides with the contract.
Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/spi/IndexFieldProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/spi/IndexFieldProvider.java?rev=1876830&r1=1876829&r2=1876830&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/spi/IndexFieldProvider.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/spi/IndexFieldProvider.java Wed Apr 22 14:52:46 2020
@@ -25,7 +25,11 @@ import java.util.Set;
/**
* Implementations of this interface would get callbacks while indexing documents. It's the responsibility
* of the implementation to exit as early as possible if it doesn't care about the document being indexed.
+ *
+ * @deprecated This interface exposes Lucene API directly - it will be removed soon.
+ * Use the "dynamicBoost" feature instead.
*/
+@Deprecated
public interface IndexFieldProvider {
/**
* Implementation which doesn't do anything useful... yet, abides with the contract.
Added: 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=1876830&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/DynamicBoostTest.java (added)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/DynamicBoostTest.java Wed Apr 22 14:52:46 2020
@@ -0,0 +1,181 @@
+/*
+ * 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.lucene.dynamicBoost;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.oak.Oak;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.ContentRepository;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.commons.junit.LogCustomizer;
+import org.apache.jackrabbit.oak.plugins.index.lucene.IndexAugmentorFactory;
+import org.apache.jackrabbit.oak.plugins.index.lucene.IndexTracker;
+import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneDocumentMaker;
+import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants;
+import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexEditorProvider;
+import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexProvider;
+import org.apache.jackrabbit.oak.plugins.index.lucene.TestUtil;
+import org.apache.jackrabbit.oak.plugins.index.lucene.spi.IndexFieldProvider;
+import org.apache.jackrabbit.oak.plugins.index.search.ExtractedTextCache;
+import org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants;
+import org.apache.jackrabbit.oak.plugins.index.search.IndexFormatVersion;
+import org.apache.jackrabbit.oak.plugins.nodetype.write.NodeTypeRegistry;
+import org.apache.jackrabbit.oak.query.AbstractQueryTest;
+import org.apache.jackrabbit.oak.spi.commit.Observer;
+import org.apache.jackrabbit.oak.spi.mount.Mounts;
+import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider;
+import org.apache.jackrabbit.oak.spi.security.OpenSecurityProvider;
+import org.junit.Test;
+
+import ch.qos.logback.classic.Level;
+
+/**
+ * Tests the index augmentation feature.
+ */
+public class DynamicBoostTest extends AbstractQueryTest {
+
+ public static final String ASSET_NODE_TYPE =
+ "[dam:Asset]\n" +
+ " - * (UNDEFINED) multiple\n" +
+ " - * (UNDEFINED)\n" +
+ " + * (nt:base) = oak:TestNode VERSION";
+
+ private static final String UNSTRUCTURED = "nt:unstructured";
+
+ private final SimpleIndexAugmentorFactory factory = new SimpleIndexAugmentorFactory();
+
+ @Override
+ protected void createTestIndexNode() throws Exception {
+ setTraversalEnabled(false);
+ }
+
+ @Override
+ protected ContentRepository createRepository() {
+ IndexTracker tracker = new IndexTracker();
+ LuceneIndexEditorProvider editorProvider = new LuceneIndexEditorProvider(null,
+ new ExtractedTextCache(0, 0),
+ factory, Mounts.defaultMountInfoProvider());
+ LuceneIndexProvider provider = new LuceneIndexProvider(tracker,
+ factory);
+ return new Oak()
+ .with(new OpenSecurityProvider())
+ .with((QueryIndexProvider) provider)
+ .with((Observer) provider)
+ .with(editorProvider)
+ .createContentRepository();
+ }
+
+ @Test public void withFieldProvider() throws Exception {
+ NodeTypeRegistry.register(root, toInputStream(ASSET_NODE_TYPE), "test nodeType");
+ createIndex("dam:Asset");
+ root.commit();
+ factory.indexFieldProvider = new IndexFieldProviderImpl();
+
+ String log = runTest(IndexFieldProviderImpl.class);
+ assertEquals(
+ "[" +
+ "Added augmented fields: jcr:content/metadata/predictedTags/[my, a, my:a], 10.0" +
+ "]", log);
+ }
+
+ @Test public void withDynamicBoost() throws Exception {
+ NodeTypeRegistry.register(root, toInputStream(ASSET_NODE_TYPE), "test nodeType");
+ Tree props = createIndex("dam:Asset");
+ Tree pt = createNodeWithType(props, "predictedTags", UNSTRUCTURED);
+ pt.setProperty("name", "jcr:content/metadata/predictedTags/.*");
+ pt.setProperty("isRegexp", true);
+ pt.setProperty("dynamicBoost", true);
+ pt.setProperty("propertyIndex", true);
+ root.commit();
+
+ String log = runTest(LuceneDocumentMaker.class);
+ 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" +
+ "]", log);
+ }
+
+ private String runTest(Class<?> loggerClass) throws CommitFailedException {
+ LogCustomizer customLogs = LogCustomizer
+ .forLogger(loggerClass)
+ .enable(Level.TRACE).create();
+ customLogs.starting();
+ try {
+ Tree test = createNodeWithType(root.getTree("/"), "test", UNSTRUCTURED);
+ Tree node = createNodeWithType(test, "item", "dam:Asset");
+ Tree predicted =
+ createNodeWithType(
+ createNodeWithType(
+ createNodeWithType(node, JcrConstants.JCR_CONTENT, UNSTRUCTURED),
+ "metadata", UNSTRUCTURED),
+ "predictedTags", UNSTRUCTURED);
+ Tree t = createNodeWithType(predicted, "a", UNSTRUCTURED);
+ t.setProperty("name", "my:a");
+ t.setProperty("confidence", 10.0);
+ root.commit();
+ // this is not detected
+ t.setProperty("confidence", 20);
+ root.commit();
+ // now we change an indexed property:
+ // this is detected in the dynamicBoost case
+ t.getParent().setProperty("updateCount", 2);
+ t.setProperty("confidence", 30);
+ root.commit();
+ return customLogs.getLogs().toString();
+ } finally {
+ customLogs.finished();
+ }
+ }
+
+ 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 Tree createIndex(String nodeType) throws Exception {
+ Tree rootTree = root.getTree("/");
+ Tree index = createTestIndexNode(rootTree, LuceneIndexConstants.TYPE_LUCENE);
+ index.setProperty(FulltextIndexConstants.COMPAT_MODE, IndexFormatVersion.V2.getVersion());
+ return TestUtil.newRulePropTree(index, nodeType);
+ }
+
+ private static class SimpleIndexAugmentorFactory extends IndexAugmentorFactory {
+ IndexFieldProvider indexFieldProvider = IndexFieldProvider.DEFAULT;
+
+ @Override
+ public IndexFieldProvider getIndexFieldProvider(String nodeType) {
+ return indexFieldProvider;
+ }
+
+ }
+
+ private static InputStream toInputStream(String x) {
+ return new ByteArrayInputStream(x.getBytes());
+ }
+
+}
Added: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/FulltextQueryTermsProviderImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/FulltextQueryTermsProviderImpl.java?rev=1876830&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/FulltextQueryTermsProviderImpl.java (added)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/FulltextQueryTermsProviderImpl.java Wed Apr 22 14:52:46 2020
@@ -0,0 +1,150 @@
+/*
+ * 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.lucene.dynamicBoost;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.jackrabbit.oak.plugins.index.lucene.spi.FulltextQueryTermsProvider;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.TermQuery;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * An example fulltext query terms provider.
+ */
+public class FulltextQueryTermsProviderImpl implements FulltextQueryTermsProvider {
+
+ private static final Logger LOG = LoggerFactory.getLogger(FulltextQueryTermsProviderImpl.class);
+ private static final String SEARCH_SPLIT_REGEX = "[ ]";
+ private static final String NT_DAM_ASSET = "dam:Asset";
+ private static final String PREDICTED_TAGS_REL_PATH = "";
+ private static final int MAX_FRAGMENT_SIZE = 2;
+ private static final int MAX_QUERY_SIZE = 10;
+
+ @Override
+ public Set<String> getSupportedTypes() {
+ Set<String> supportedTypes = new HashSet<String>();
+ supportedTypes.add(NT_DAM_ASSET);
+ return supportedTypes;
+ }
+
+ @Override
+ public org.apache.lucene.search.Query getQueryTerm(String text, Analyzer analyzer, NodeState indexDefinition) {
+ if (analyzer == null || text == null) {
+ return null;
+ }
+
+ LOG.debug("getQueryTerm Text: {}", text);
+ BooleanQuery query = this.createQuery();
+
+ Set<String> charTerms = new HashSet<String>(splitForSearch(text));
+ LOG.debug("getQueryTerm charTerms: {}", charTerms);
+ if(charTerms.size() > MAX_QUERY_SIZE) {
+ LOG.debug("Not adding query terms for smart tags as number of terms in the query {} exceeds " +
+ "maximum permissible value of {}", charTerms.size(), MAX_QUERY_SIZE);
+ return null;
+ }
+ List<String> fragments = prepareFragments(charTerms);
+
+ for(String fragment : fragments) {
+ Term term = new Term(PREDICTED_TAGS_REL_PATH + fragment.toLowerCase(), "1");
+ query.add(new TermQuery(term), BooleanClause.Occur.SHOULD);
+ LOG.debug("Added query term: {}", fragment.toLowerCase());
+ }
+
+
+ Term term = new Term(PREDICTED_TAGS_REL_PATH + text.toLowerCase(), "1");
+ query.add(new TermQuery(term), BooleanClause.Occur.SHOULD);
+ LOG.debug("Added query term: {}", text.toLowerCase());
+
+ //De-boosting smart tags based query.
+ query.setBoost(0.0001f);
+ return query;
+
+ }
+
+ private List<String> prepareFragments(Set<String> charTerms) {
+
+ List<String> fragments = new ArrayList<String>();
+ Set<Set<String>> powerSet = powerSet(charTerms);
+
+ for(Set<String> set : powerSet) {
+ StringBuilder sb = null;
+ for(String s : set) {
+ if(sb == null) {
+ sb = new StringBuilder();
+ }
+ sb.append(s);
+ if(sb.length() > 0) {
+ sb.append(' ');
+ }
+ }
+ if(sb != null) {
+ fragments.add(sb.toString().trim());
+ }
+ }
+
+ return fragments;
+ }
+
+ private <T> Set<Set<T>> powerSet(Set<T> originalSet) {
+ Set<Set<T>> powerSet = new HashSet<Set<T>>();
+ if (originalSet.isEmpty()) {
+ powerSet.add(new HashSet<T>());
+ return powerSet;
+ }
+ List<T> list = new ArrayList<T>(originalSet);
+ T head = list.get(0);
+ Set<T> rest = new HashSet<T>(list.subList(1, list.size()));
+ for (Set<T> subsetExcludingHead : powerSet(rest)) {
+ Set<T> subsetIncludingHead = new HashSet<T>();
+ subsetIncludingHead.add(head);
+ subsetIncludingHead.addAll(subsetExcludingHead);
+ if(subsetIncludingHead.size() <= MAX_FRAGMENT_SIZE) {
+ powerSet.add(subsetIncludingHead);
+ }
+ if(subsetExcludingHead.size() <= MAX_FRAGMENT_SIZE) {
+ powerSet.add(subsetExcludingHead);
+ }
+ }
+ return powerSet;
+ }
+
+ private List<String> splitForSearch(String tagName) {
+ return Arrays.asList(removeBackSlashes(tagName).split(SEARCH_SPLIT_REGEX));
+ }
+
+ private String removeBackSlashes(String text) {
+ return text.replaceAll("\\\\", "");
+ }
+
+ protected BooleanQuery createQuery() {
+ return new BooleanQuery();
+ }
+
+}
Added: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/IndexFieldProviderImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/IndexFieldProviderImpl.java?rev=1876830&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/IndexFieldProviderImpl.java (added)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/dynamicBoost/IndexFieldProviderImpl.java Wed Apr 22 14:52:46 2020
@@ -0,0 +1,112 @@
+/*
+ * 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.lucene.dynamicBoost;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.plugins.index.lucene.spi.IndexFieldProvider;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import static com.google.common.collect.Sets.newHashSet;
+
+/**
+ * An example index field provider.
+ */
+public class IndexFieldProviderImpl implements IndexFieldProvider {
+
+ private static final Logger LOG = LoggerFactory.getLogger(IndexFieldProviderImpl.class);
+
+ private static final String METADATA_FOLDER = "metadata";
+ private static final String PREDICTED_TAGS = "predictedTags";
+ private static final String PREDICTED_TAG_NAME = "name";
+ private static final String PREDICTED_TAG_CONFIDENCE = "confidence";
+ private static final String PREDICTED_TAGS_REL_PATH = JcrConstants.JCR_CONTENT + "/" + METADATA_FOLDER + "/" +
+ PREDICTED_TAGS + "/";
+ private static final String INDEXING_SPLIT_REGEX = "[:/]";
+ private static final String NT_DAM_ASSET = "dam:Asset";
+
+ @Override
+ public Set<String> getSupportedTypes() {
+ Set<String> supportedTypes = new HashSet<String>();
+ supportedTypes.add(NT_DAM_ASSET);
+ return supportedTypes;
+ }
+
+ @Override
+ public @NotNull Iterable<Field> getAugmentedFields(String path, NodeState nodeState, NodeState indexDefinition) {
+ Set<Field> fields = newHashSet();
+ NodeState dynaTags = nodeState.getChildNode(JcrConstants.JCR_CONTENT).getChildNode(METADATA_FOLDER).getChildNode(PREDICTED_TAGS);
+ for (String nodeName : dynaTags.getChildNodeNames()) {
+ NodeState dynaTag = dynaTags.getChildNode(nodeName);
+ String dynaTagName = dynaTag.getProperty(PREDICTED_TAG_NAME).getValue(Type.STRING);
+ Double dynaTagConfidence = dynaTag.getProperty(PREDICTED_TAG_CONFIDENCE).getValue(Type.DOUBLE);
+
+ List<String> tokens = new ArrayList<>(splitForIndexing(dynaTagName));
+ if (tokens.size() > 1) { // Actual name not in tokens
+ tokens.add(dynaTagName);
+ }
+ for (String token : tokens) {
+ if (token.length() > 0) {
+ fields.add(new AugmentedField(PREDICTED_TAGS_REL_PATH + token.toLowerCase(), dynaTagConfidence));
+ }
+ }
+ LOG.trace(
+ "Added augmented fields: {}[{}], {}",
+ PREDICTED_TAGS_REL_PATH, String.join(", ", tokens), dynaTagConfidence
+ );
+ }
+ return fields;
+ }
+
+ private static class AugmentedField extends Field {
+ private static final FieldType ft = new FieldType();
+ static {
+ ft.setIndexed(true);
+ ft.setStored(false);
+ ft.setTokenized(false);
+ ft.setOmitNorms(false);
+ ft.setIndexOptions(org.apache.lucene.index.FieldInfo.IndexOptions.DOCS_ONLY);
+ ft.freeze();
+ }
+
+ AugmentedField(String name, double weight) {
+ super(name, "1", ft);
+ setBoost((float) weight);
+ }
+ }
+
+ private static List<String> splitForIndexing(String tagName) {
+ return Arrays.asList(removeBackSlashes(tagName).split(INDEXING_SPLIT_REGEX));
+ }
+
+ private static String removeBackSlashes(String text) {
+ return text.replaceAll("\\\\", "");
+ }
+
+}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elasticsearch/index/ElasticsearchDocumentMaker.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elasticsearch/index/ElasticsearchDocumentMaker.java?rev=1876830&r1=1876829&r2=1876830&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elasticsearch/index/ElasticsearchDocumentMaker.java (original)
+++ jackrabbit/oak/trunk/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elasticsearch/index/ElasticsearchDocumentMaker.java Wed Apr 22 14:52:46 2020
@@ -186,4 +186,11 @@ class ElasticsearchDocumentMaker extends
// TODO : not implemented
return false;
}
+
+ @Override
+ protected boolean indexDynamicBoost(ElasticsearchDocument doc, PropertyDefinition pd, NodeState nodeState,
+ String propertyName) {
+ // TODO : not implemented
+ return false;
+ }
}
Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/FulltextIndexConstants.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/FulltextIndexConstants.java?rev=1876830&r1=1876829&r2=1876830&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/FulltextIndexConstants.java (original)
+++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/FulltextIndexConstants.java Wed Apr 22 14:52:46 2020
@@ -138,6 +138,8 @@ public interface FulltextIndexConstants
String PROP_WEIGHT = "weight";
+ String PROP_DYNAMIC_BOOST = "dynamicBoost";
+
/**
* Boolean property in property definition to mark sync properties
*/
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=1876830&r1=1876829&r2=1876830&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 Apr 22 14:52:46 2020
@@ -102,6 +102,8 @@ public class PropertyDefinition {
public final int weight;
+ public final boolean dynamicBoost;
+
/**
* Property name excluding the relativePath. For regular expression based definition
* its set to null
@@ -136,6 +138,7 @@ public class PropertyDefinition {
this.relative = isRelativeProperty(name);
this.boost = getOptionalValue(defn, FIELD_BOOST, DEFAULT_BOOST);
this.weight = getOptionalValue(defn, PROP_WEIGHT, DEFAULT_PROPERTY_WEIGHT);
+ this.dynamicBoost = getOptionalValue(defn, FulltextIndexConstants.PROP_DYNAMIC_BOOST, false);
//By default if a property is defined it is indexed
this.index = getOptionalValue(defn, FulltextIndexConstants.PROP_INDEX, true);
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=1876830&r1=1876829&r2=1876830&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 Apr 22 14:52:46 2020
@@ -101,6 +101,8 @@ 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);
+
protected abstract void indexAncestors(D doc, String path);
protected abstract void indexNotNullProperty(D doc, PropertyDefinition pd);
@@ -244,6 +246,9 @@ public abstract class FulltextDocumentMa
if (pd.propertyIndex && pd.includePropertyType(property.getType().tag())) {
dirty |= addTypedFields(doc, property, pname, pd);
}
+ if (pd.dynamicBoost) {
+ dirty |= indexDynamicBoost(doc, pd, state, pname);
+ }
if (pd.fulltextEnabled() && includeTypeForFullText) {
for (String value : property.getValue(Type.STRINGS)) {