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 to...@apache.org on 2015/12/18 09:01:17 UTC

svn commit: r1720726 - in /jackrabbit/oak/trunk/oak-lucene/src: main/java/org/apache/jackrabbit/oak/plugins/index/lucene/ main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/ test/java/org/apache/jackrabbit/oak/jcr/query/

Author: tommaso
Date: Fri Dec 18 08:01:17 2015
New Revision: 1720726

URL: http://svn.apache.org/viewvc?rev=1720726&view=rev
Log:
OAK-2511 - tweak facet impl for lucene

Added:
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/FacetHelper.java   (with props)
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/FilteredSortedSetDocValuesFacetCounts.java   (with props)
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/NodeStateFacetsConfig.java   (with props)
Modified:
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/FieldNames.java
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexConstants.java
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditor.java
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorContext.java
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/PropertyDefinition.java
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/package-info.java
    jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/FacetTest.java

Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/FieldNames.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/FieldNames.java?rev=1720726&r1=1720725&r2=1720726&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/FieldNames.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/FieldNames.java Fri Dec 18 08:01:17 2015
@@ -119,4 +119,8 @@ public final class FieldNames {
         }
         return FULLTEXT_RELATIVE_NODE + nodeRelativePath;
     }
+
+    public static String createFacetFieldName(String pname) {
+        return pname + "_facet";
+    }
 }

Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java?rev=1720726&r1=1720725&r2=1720726&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexDefinition.java Fri Dec 18 08:01:17 2015
@@ -79,28 +79,13 @@ import static org.apache.jackrabbit.oak.
 import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.DECLARING_NODE_TYPES;
 import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.ENTRY_COUNT_PROPERTY_NAME;
 import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.REINDEX_COUNT;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.ACTIVE_DELETE;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.BLOB_SIZE;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.COMPAT_MODE;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.EVALUATE_PATH_RESTRICTION;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.EXCLUDE_PROPERTY_NAMES;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.EXPERIMENTAL_STORAGE;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.FIELD_BOOST;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.FULL_TEXT_ENABLED;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.INCLUDE_PROPERTY_NAMES;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.INCLUDE_PROPERTY_TYPES;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.INDEX_DATA_CHILD_NAME;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.ORDERED_PROP_NAMES;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.PROP_NAME;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.PROP_NODE;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.TIKA;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.TIKA_CONFIG;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.*;
 import static org.apache.jackrabbit.oak.plugins.index.lucene.PropertyDefinition.DEFAULT_BOOST;
 import static org.apache.jackrabbit.oak.plugins.index.lucene.util.ConfigUtil.getOptionalValue;
 import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.NODE_TYPES_PATH;
 
-class IndexDefinition implements Aggregate.AggregateMapper{
+class IndexDefinition implements Aggregate.AggregateMapper {
     /**
      * Name of the internal property that contains the child order defined in
      * org.apache.jackrabbit.oak.plugins.tree.impl.TreeConstants
@@ -288,7 +273,7 @@ class IndexDefinition implements Aggrega
         this.queryPaths = getQueryPaths(defn);
         this.saveDirListing = getOptionalValue(defn, LuceneIndexConstants.SAVE_DIR_LISTING, true);
         this.suggestAnalyzed = getOptionalValue(defn, LuceneIndexConstants.SUGGEST_ANALYZED, false);
-        this.secureFacets = getOptionalValue(defn, LuceneIndexConstants.PROP_SECURE_FACETS, true);
+        this.secureFacets = defn.hasChildNode(PROP_FACET) && getOptionalValue(defn.getChildNode(PROP_FACET), PROP_SECURE_FACETS, true);
     }
 
     public NodeState getDefinitionNodeState() {

Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java?rev=1720726&r1=1720725&r2=1720726&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java Fri Dec 18 08:01:17 2015
@@ -21,6 +21,7 @@ package org.apache.jackrabbit.oak.plugin
 
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -29,8 +30,11 @@ import javax.annotation.CheckForNull;
 
 import com.google.common.collect.Iterables;
 import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.plugins.index.lucene.IndexDefinition.IndexingRule;
+import org.apache.jackrabbit.oak.plugins.index.lucene.util.FacetHelper;
+import org.apache.jackrabbit.oak.query.QueryImpl;
 import org.apache.jackrabbit.oak.query.fulltext.FullTextContains;
 import org.apache.jackrabbit.oak.query.fulltext.FullTextExpression;
 import org.apache.jackrabbit.oak.query.fulltext.FullTextTerm;
@@ -144,12 +148,18 @@ class IndexPlanner {
 
         //Optimization - Go further only if any of the property is configured
         //for property index
+        List<String> facetFields = new LinkedList<String>();
         if (indexingRule.propertyIndexEnabled) {
             for (PropertyRestriction pr : filter.getPropertyRestrictions()) {
                 String name = pr.propertyName;
                 if (QueryConstants.RESTRICTION_LOCAL_NAME.equals(name)) {
                     continue;
-                }                
+                }
+                if (QueryImpl.REP_FACET.equals(pr.propertyName)) {
+                    String value = pr.first.getValue(Type.STRING);
+                    facetFields.add(FacetHelper.parseFacetField(value));
+                }
+
                 PropertyDefinition pd = indexingRule.getConfig(pr.propertyName);
                 if (pd != null && pd.propertyIndexEnabled()) {
                     if (pr.isNullRestriction() && !pd.nullCheckEnabled){
@@ -193,6 +203,10 @@ class IndexPlanner {
                 costPerEntryFactor = 1;
             }
 
+            if (facetFields.size() > 0) {
+                plan.setAttribute(FacetHelper.ATTR_FACET_FIELDS, facetFields);
+            }
+
             if (ft == null){
                 result.enableNonFullTextConstraints();
             }

Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexConstants.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexConstants.java?rev=1720726&r1=1720725&r2=1720726&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexConstants.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexConstants.java Fri Dec 18 08:01:17 2015
@@ -287,8 +287,7 @@ public interface LuceneIndexConstants {
     String INDEX_PATH = "indexPath";
 
     /**
-     * Optional (property definition) property indicating facet can be retrieved together with plain queries.
-     * Default is false
+     * Optional property definition subnode holding configuration for facets.
      */
     String PROP_FACET = "facets";
 

Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditor.java?rev=1720726&r1=1720725&r2=1720726&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditor.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditor.java Fri Dec 18 08:01:17 2015
@@ -16,19 +16,7 @@
  */
 package org.apache.jackrabbit.oak.plugins.index.lucene;
 
-import static org.apache.jackrabbit.JcrConstants.JCR_CREATED;
-import static org.apache.jackrabbit.JcrConstants.JCR_DATA;
-import static org.apache.jackrabbit.JcrConstants.JCR_UUID;
-import static org.apache.jackrabbit.oak.commons.PathUtils.concat;
-import static org.apache.jackrabbit.oak.commons.PathUtils.getName;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.FieldFactory.newDepthField;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.FieldFactory.newFulltextField;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.FieldFactory.newAncestorsField;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.FieldFactory.newPathField;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.FieldFactory.newPropertyField;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.TermFactory.newPathTerm;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.util.ConfigUtil.getPrimaryTypeName;
-
+import javax.annotation.Nullable;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -36,11 +24,8 @@ import java.util.List;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-import javax.annotation.Nullable;
-
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
-
 import com.google.common.collect.Sets;
 import com.google.common.io.CountingInputStream;
 import org.apache.jackrabbit.JcrConstants;
@@ -71,7 +56,6 @@ import org.apache.lucene.document.LongFi
 import org.apache.lucene.document.NumericDocValuesField;
 import org.apache.lucene.document.SortedDocValuesField;
 import org.apache.lucene.document.StringField;
-import org.apache.lucene.facet.FacetsConfig;
 import org.apache.lucene.facet.sortedset.SortedSetDocValuesFacetField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.search.PrefixQuery;
@@ -82,6 +66,13 @@ import org.apache.tika.sax.WriteOutConte
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.jackrabbit.JcrConstants.JCR_DATA;
+import static org.apache.jackrabbit.oak.commons.PathUtils.concat;
+import static org.apache.jackrabbit.oak.commons.PathUtils.getName;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.FieldFactory.*;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.TermFactory.newPathTerm;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.util.ConfigUtil.getPrimaryTypeName;
+
 /**
  * {@link IndexEditor} implementation that is responsible for keeping the
  * {@link LuceneIndex} up to date
@@ -128,8 +119,6 @@ public class LuceneIndexEditor implement
 
     private final PathFilter.Result pathFilterResult;
 
-    private static final FacetsConfig facetsConfig = new FacetsConfig();
-
     LuceneIndexEditor(NodeState root, NodeBuilder definition,
                         IndexUpdateCallback updateCallback,
                         @Nullable IndexCopier indexCopier,
@@ -343,12 +332,9 @@ public class LuceneIndexEditor implement
                 dirty |= addTypedOrderedFields(fields, property, pname, pd);
             }
 
-            if (pd.facet) {
-                dirty |= addFacetFields(fields, property, pname, pd);
-                facet = true;
-            }
-
             dirty |= indexProperty(path, fields, state, property, pname, pd);
+
+            facet |= pd.facet;
         }
 
         dirty |= indexAggregates(path, fields, state);
@@ -408,7 +394,7 @@ public class LuceneIndexEditor implement
         }
 
         if (facet) {
-            document = facetsConfig.build(document);
+            document = context.getFacetsConfig().build(document);
         }
 
         //TODO Boost at document level
@@ -417,64 +403,46 @@ public class LuceneIndexEditor implement
     }
 
     private boolean addFacetFields(List<Field> fields, PropertyState property, String pname, PropertyDefinition pd) {
-        // force skipping some JCR properties whose faceting wouldn't make sense (unique or possibly very large values)
-        if (!pname.equals(JCR_DATA) && !pname.equals(JCR_CREATED) && !pname.equals(JCR_UUID)) {
-            String facetFieldName = pname + "_facet";
-            facetsConfig.setIndexFieldName(pname, facetFieldName); // facets are indexed in *_facet fields
-            int tag = property.getType().tag();
-            int idxDefinedTag = pd.getType();
-            // Try converting type to the defined type in the index definition
-            if (tag != idxDefinedTag) {
-                log.debug("[{}] Facet property defined with type {} differs from property {} with type {} in "
-                                + "path {}",
-                        getIndexName(),
-                        Type.fromTag(idxDefinedTag, false), property.toString(),
-                        Type.fromTag(tag, false), getPath());
-                tag = idxDefinedTag;
-            }
+        String facetFieldName = FieldNames.createFacetFieldName(pname);
+        context.getFacetsConfig().setIndexFieldName(pname, facetFieldName);
+        int tag = property.getType().tag();
+        int idxDefinedTag = pd.getType();
+        // Try converting type to the defined type in the index definition
+        if (tag != idxDefinedTag) {
+            log.debug("[{}] Facet property defined with type {} differs from property {} with type {} in "
+                            + "path {}",
+                    getIndexName(),
+                    Type.fromTag(idxDefinedTag, false), property.toString(),
+                    Type.fromTag(tag, false), getPath());
+            tag = idxDefinedTag;
+        }
 
-            boolean fieldAdded = false;
-            try {
-                if (tag == Type.LONG.tag()) {
-                    fields.add(new SortedSetDocValuesFacetField(pname, property.getValue(Type.LONG).toString()));
-                    fieldAdded = true;
-                } else if (tag == Type.DATE.tag()) {
-                    String date = property.getValue(Type.DATE);
-                    fields.add(new SortedSetDocValuesFacetField(pname, date));
-                    fieldAdded = true;
-                } else if (tag == Type.DOUBLE.tag()) {
-                    fields.add(new DoubleDocValuesField(pname, property.getValue(Type.DOUBLE)));
-                    fieldAdded = true;
-                } else if (tag == Type.BOOLEAN.tag()) {
-                    fields.add(new SortedSetDocValuesFacetField(pname, property.getValue(Type.BOOLEAN).toString()));
-                    fieldAdded = true;
-                } else if (tag == Type.STRINGS.tag() && property.isArray()) {
-                    facetsConfig.setMultiValued(pname, true);
-                    Iterable<String> values = property.getValue(Type.STRINGS);
-                    for (String value : values) {
-                        if (value != null && value.length() > 0) {
-                            fields.add(new SortedSetDocValuesFacetField(pname, value));
-                        }
-                    }
-                    fieldAdded = true;
-                } else if (tag == Type.STRING.tag()) {
-                    String value = property.getValue(Type.STRING);
-                    if (value.length() > 0) {
+        boolean fieldAdded = false;
+        try {
+            if (tag == Type.STRINGS.tag() && property.isArray()) {
+                context.getFacetsConfig().setMultiValued(pname, true);
+                Iterable<String> values = property.getValue(Type.STRINGS);
+                for (String value : values) {
+                    if (value != null && value.length() > 0) {
                         fields.add(new SortedSetDocValuesFacetField(pname, value));
-                        fieldAdded = true;
                     }
                 }
-
-            } catch (Throwable e) {
-                log.warn("[{}] Ignoring facet property. Could not convert property {} of type {} to type {} for path {}",
-                        getIndexName(), pname,
-                        Type.fromTag(property.getType().tag(), false),
-                        Type.fromTag(tag, false), getPath(), e);
+                fieldAdded = true;
+            } else if (tag == Type.STRING.tag()) {
+                String value = property.getValue(Type.STRING);
+                if (value.length() > 0) {
+                    fields.add(new SortedSetDocValuesFacetField(pname, value));
+                    fieldAdded = true;
+                }
             }
-            return fieldAdded;
-        } else {
-            return false;
+
+        } catch (Throwable e) {
+            log.warn("[{}] Ignoring facet property. Could not convert property {} of type {} to type {} for path {}",
+                    getIndexName(), pname,
+                    Type.fromTag(property.getType().tag(), false),
+                    Type.fromTag(tag, false), getPath(), e);
         }
+        return fieldAdded;
     }
 
     private boolean indexProperty(String path,
@@ -517,6 +485,10 @@ public class LuceneIndexEditor implement
                     dirty = true;
                 }
             }
+            if (pd.facet) {
+                dirty |= addFacetFields(fields, property, pname, pd);
+            }
+
             return dirty;
         }
     }

Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorContext.java?rev=1720726&r1=1720725&r2=1720726&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorContext.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexEditorContext.java Fri Dec 18 08:01:17 2015
@@ -33,6 +33,7 @@ import org.apache.jackrabbit.oak.api.Com
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.plugins.index.IndexUpdateCallback;
+import org.apache.jackrabbit.oak.plugins.index.lucene.util.FacetHelper;
 import org.apache.jackrabbit.oak.plugins.index.lucene.util.SuggestHelper;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -41,6 +42,7 @@ import org.apache.jackrabbit.util.ISO860
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.miscellaneous.PerFieldAnalyzerWrapper;
 import org.apache.lucene.analysis.shingle.ShingleAnalyzerWrapper;
+import org.apache.lucene.facet.FacetsConfig;
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
@@ -69,6 +71,8 @@ public class LuceneIndexEditorContext {
     private static final PerfLogger PERF_LOGGER =
             new PerfLogger(LoggerFactory.getLogger(LuceneIndexEditorContext.class.getName() + ".perf"));
 
+    private final FacetsConfig facetsConfig;
+
     static IndexWriterConfig getIndexWriterConfig(IndexDefinition definition, boolean remoteDir) {
         // FIXME: Hack needed to make Lucene work in an OSGi environment
         Thread thread = Thread.currentThread();
@@ -159,6 +163,7 @@ public class LuceneIndexEditorContext {
         if (this.definition.isOfOldFormat()){
             IndexDefinition.updateDefinition(definition);
         }
+        this.facetsConfig = FacetHelper.getFacetsConfig(definition);
     }
 
     Parser getParser() {
@@ -326,6 +331,10 @@ public class LuceneIndexEditorContext {
         return definition;
     }
 
+    FacetsConfig getFacetsConfig() {
+        return facetsConfig;
+    }
+
     @Deprecated
     public void recordTextExtractionStats(long timeInMillis, long bytesRead) {
         //Keeping deprecated method to avoid major version change

Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java?rev=1720726&r1=1720725&r2=1720726&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndex.java Fri Dec 18 08:01:17 2015
@@ -47,6 +47,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.index.lucene.IndexDefinition.IndexingRule;
 import org.apache.jackrabbit.oak.plugins.index.lucene.IndexPlanner.PlanResult;
 import org.apache.jackrabbit.oak.plugins.index.lucene.score.ScorerProviderFactory;
+import org.apache.jackrabbit.oak.plugins.index.lucene.util.FacetHelper;
 import org.apache.jackrabbit.oak.plugins.index.lucene.util.MoreLikeThisHelper;
 import org.apache.jackrabbit.oak.plugins.index.lucene.util.SpellcheckHelper;
 import org.apache.jackrabbit.oak.plugins.index.lucene.util.SuggestHelper;
@@ -377,15 +378,6 @@ public class LucenePropertyIndex impleme
 
                         checkForIndexVersionChange(searcher);
 
-                        List<String> facetFields = new LinkedList<String>();
-                        List<PropertyRestriction> facetRestriction = filter.getPropertyRestrictions(QueryImpl.REP_FACET);
-                        if (facetRestriction != null && facetRestriction.size() > 0) {
-                            for (PropertyRestriction pr : facetRestriction) {
-                                String value = pr.first.getValue(Type.STRING);
-                                facetFields.add(value.substring(QueryImpl.REP_FACET.length() + 1, value.length() - 1));
-                            }
-                        }
-
                         TopDocs docs;
                         long start = PERF_LOGGER.start();
                         while (true) {
@@ -407,35 +399,9 @@ public class LucenePropertyIndex impleme
                             PERF_LOGGER.end(start, -1, "{} ...", docs.scoreDocs.length);
                             nextBatchSize = (int) Math.min(nextBatchSize * 2L, 100000);
 
-                            Facets facets = null;
-                            if (facetFields.size() > 0) {
-                                Map<String, Facets> facetsMap = new HashMap<String, Facets>();
-
-                                long f = System.currentTimeMillis();
-                                for (String facetField : facetFields) {
-                                    FacetsCollector facetsCollector = new FacetsCollector();
-                                    try {
-                                        DefaultSortedSetDocValuesReaderState state = new DefaultSortedSetDocValuesReaderState(
-                                                searcher.getIndexReader(), facetField + "_facet"); // facets are indexed in *_facet fields
-                                        if (lastDoc != null) {
-                                            facetsCollector.searchAfter(searcher, lastDoc, query, 10, facetsCollector);
-                                        } else {
-                                            FacetsCollector.search(searcher, query, 10, facetsCollector);
-                                        }
-                                        facetsMap.put(facetField, indexNode.getDefinition().isSecureFacets() ?
-                                                new FilteredSortedSetDocValuesFacetCounts(state, facetsCollector, filter, docs) :
-                                                new SortedSetDocValuesFacetCounts(state, facetsCollector));
-
-                                    } catch (IllegalArgumentException iae) {
-                                        LOG.warn("facets for {} not yet indexed", facetField);
-                                    }
-                                }
-                                if (facetsMap.size() > 0) {
-                                    facets = new MultiFacets(facetsMap);
-                                    LOG.debug("facets retrieved in {}ms", (System.currentTimeMillis() - f));
-                                }
-
-                            }
+                            long f = PERF_LOGGER.start();
+                            Facets facets = FacetHelper.getFacets(searcher, query, docs, plan, indexNode.getDefinition().isSecureFacets());
+                            PERF_LOGGER.end(f, -1, "facets retrieved");
 
                             PropertyRestriction restriction = filter.getPropertyRestriction(QueryImpl.REP_EXCERPT);
                             boolean addExcerpt = restriction != null && restriction.isNotNullRestriction();
@@ -530,6 +496,7 @@ public class LucenePropertyIndex impleme
                 return !queue.isEmpty();
             }
 
+
             private void checkForIndexVersionChange(IndexSearcher searcher) {
                 long currentVersion = getVersion(searcher);
                 if (currentVersion != lastSearchIndexerVersion && lastDoc != null) {
@@ -1507,7 +1474,7 @@ public class LucenePropertyIndex impleme
                         return PropertyValues.newString(currentRow.excerpt);
                     }
                     if (columnName.startsWith(QueryImpl.REP_FACET)) {
-                        String facetFieldName = columnName.substring(QueryImpl.REP_FACET.length() + 1, columnName.length() - 1);
+                        String facetFieldName = FacetHelper.parseFacetField(columnName);
                         Facets facets = currentRow.facets;
                         try {
                             if (facets != null) {
@@ -1565,79 +1532,4 @@ public class LucenePropertyIndex impleme
         }
     }
 
-    private class FilteredSortedSetDocValuesFacetCounts extends SortedSetDocValuesFacetCounts {
-        private final TopDocs docs;
-        private final Filter filter;
-        private final IndexReader reader;
-        private final SortedSetDocValuesReaderState state;
-
-        public FilteredSortedSetDocValuesFacetCounts(DefaultSortedSetDocValuesReaderState state, FacetsCollector facetsCollector, Filter filter, TopDocs docs) throws IOException {
-            super(state, facetsCollector);
-            this.reader = state.origReader;
-            this.filter = filter;
-            this.docs = docs;
-            this.state = state;
-        }
-
-        @Override
-        public FacetResult getTopChildren(int topN, String dim, String... path) throws IOException {
-            FacetResult topChildren = super.getTopChildren(topN, dim, path);
-
-            LabelAndValue[] labelAndValues = topChildren.labelValues;
-
-            for (ScoreDoc scoreDoc : docs.scoreDocs) {
-                labelAndValues = filterFacet(scoreDoc.doc, dim, labelAndValues);
-            }
-
-            int childCount = labelAndValues.length;
-            Number value = 0;
-            for (LabelAndValue lv : labelAndValues) {
-                value = value.longValue() + lv.value.longValue();
-            }
-
-            return new FacetResult(dim, path, value, labelAndValues, childCount);
-        }
-
-        private LabelAndValue[] filterFacet(int docId, String dimension, LabelAndValue[] labelAndValues) throws IOException {
-            boolean filterd = false;
-            Map<String, Long> newValues = new HashMap<String, Long>();
-
-            Document document = reader.document(docId);
-            SortedSetDocValues docValues = state.getDocValues();
-            docValues.setDocument(docId);
-
-            // filter using doc values (avoiding requiring stored values)
-            if (!filter.isAccessible(document.getField(PATH).stringValue() + "/" + dimension)) {
-                filterd = true;
-                for (LabelAndValue lv : labelAndValues) {
-                    long existingCount = lv.value.longValue();
-
-                    BytesRef key = new BytesRef(FacetsConfig.pathToString(dimension, new String[]{lv.label}));
-                    long l = docValues.lookupTerm(key);
-                    if (l >= 0) {
-                        if (existingCount > 0) {
-                            newValues.put(lv.label, existingCount - 1);
-                        } else {
-                            if (newValues.containsKey(lv.label)) {
-                                newValues.remove(lv.label);
-                            }
-                        }
-                    }
-                }
-            }
-            LabelAndValue[] filteredLVs;
-            if (filterd) {
-                filteredLVs = new LabelAndValue[newValues.size()];
-                int i = 0;
-                for (Map.Entry<String, Long> entry : newValues.entrySet()) {
-                    filteredLVs[i] = new LabelAndValue(entry.getKey(), entry.getValue());
-                    i++;
-                }
-            } else {
-                filteredLVs = labelAndValues;
-            }
-
-            return filteredLVs;
-        }
-    }
 }

Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/PropertyDefinition.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/PropertyDefinition.java?rev=1720726&r1=1720725&r2=1720726&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/PropertyDefinition.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/PropertyDefinition.java Fri Dec 18 08:01:17 2015
@@ -36,6 +36,7 @@ import static com.google.common.collect.
 import static org.apache.jackrabbit.oak.commons.PathUtils.elements;
 import static org.apache.jackrabbit.oak.commons.PathUtils.isAbsolute;
 import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.FIELD_BOOST;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.PROP_FACET;
 import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.PROP_IS_REGEX;
 import static org.apache.jackrabbit.oak.plugins.index.lucene.util.ConfigUtil.getOptionalValue;
 
@@ -130,7 +131,7 @@ class PropertyDefinition {
         this.notNullCheckEnabled = getOptionalValueIfIndexed(defn, LuceneIndexConstants.PROP_NOT_NULL_CHECK_ENABLED, false);
         this.nonRelativeName = determineNonRelativeName();
         this.ancestors = computeAncestors(name);
-        this.facet = getOptionalValue(defn, LuceneIndexConstants.PROP_FACET, false);
+        this.facet = defn.hasChildNode(PROP_FACET) && getOptionalValue(defn.getChildNode(PROP_FACET), "enabled", false);
         validate();
     }
 

Added: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/FacetHelper.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/FacetHelper.java?rev=1720726&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/FacetHelper.java (added)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/FacetHelper.java Fri Dec 18 08:01:17 2015
@@ -0,0 +1,91 @@
+/*
+ * 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.util;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.jackrabbit.oak.plugins.index.lucene.FieldNames;
+import org.apache.jackrabbit.oak.query.QueryImpl;
+import org.apache.jackrabbit.oak.spi.query.QueryIndex;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.lucene.facet.Facets;
+import org.apache.lucene.facet.FacetsCollector;
+import org.apache.lucene.facet.FacetsConfig;
+import org.apache.lucene.facet.MultiFacets;
+import org.apache.lucene.facet.sortedset.DefaultSortedSetDocValuesReaderState;
+import org.apache.lucene.facet.sortedset.SortedSetDocValuesFacetCounts;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TopDocs;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ */
+public class FacetHelper {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(FacetHelper.class);
+
+    /**
+     * IndexPaln Attribute name which refers to the name of the fields that should used for facets.
+     */
+    public static final String ATTR_FACET_FIELDS = "oak.facet.fields";
+
+    public static FacetsConfig getFacetsConfig(NodeBuilder definition) {
+        return new NodeStateFacetsConfig(definition);
+    }
+
+    public static Facets getFacets(IndexSearcher searcher, Query query, TopDocs docs, QueryIndex.IndexPlan plan, boolean secure) throws IOException {
+        Facets facets = null;
+        @SuppressWarnings("unchecked")
+        List<String> facetFields = (List<String>) plan.getAttribute(ATTR_FACET_FIELDS);
+        if (facetFields != null && facetFields.size() > 0) {
+            Map<String, Facets> facetsMap = new HashMap<String, Facets>();
+
+            for (String facetField : facetFields) {
+                FacetsCollector facetsCollector = new FacetsCollector();
+                try {
+                    DefaultSortedSetDocValuesReaderState state = new DefaultSortedSetDocValuesReaderState(
+                            searcher.getIndexReader(), FieldNames.createFacetFieldName(facetField));
+                        FacetsCollector.search(searcher, query, 10, facetsCollector);
+                    facetsMap.put(facetField, secure ?
+                            new FilteredSortedSetDocValuesFacetCounts(state, facetsCollector, plan.getFilter(), docs) :
+                            new SortedSetDocValuesFacetCounts(state, facetsCollector));
+
+                } catch (IllegalArgumentException iae) {
+                    LOGGER.warn("facets for {} not yet indexed", facetField);
+                }
+            }
+            if (facetsMap.size() > 0) {
+                facets = new MultiFacets(facetsMap);
+            }
+
+        }
+        return facets;
+    }
+
+
+    public static String parseFacetField(String columnName) {
+        return columnName.substring(QueryImpl.REP_FACET.length() + 1, columnName.length() - 1);
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/FacetHelper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/FilteredSortedSetDocValuesFacetCounts.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/FilteredSortedSetDocValuesFacetCounts.java?rev=1720726&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/FilteredSortedSetDocValuesFacetCounts.java (added)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/FilteredSortedSetDocValuesFacetCounts.java Fri Dec 18 08:01:17 2015
@@ -0,0 +1,118 @@
+/*
+ * 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.util;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.jackrabbit.oak.plugins.index.lucene.FieldNames;
+import org.apache.jackrabbit.oak.spi.query.Filter;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.facet.FacetResult;
+import org.apache.lucene.facet.FacetsCollector;
+import org.apache.lucene.facet.FacetsConfig;
+import org.apache.lucene.facet.LabelAndValue;
+import org.apache.lucene.facet.sortedset.DefaultSortedSetDocValuesReaderState;
+import org.apache.lucene.facet.sortedset.SortedSetDocValuesFacetCounts;
+import org.apache.lucene.facet.sortedset.SortedSetDocValuesReaderState;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.SortedSetDocValues;
+import org.apache.lucene.search.ScoreDoc;
+import org.apache.lucene.search.TopDocs;
+import org.apache.lucene.util.BytesRef;
+
+/**
+ * ACL filtered version of {@link SortedSetDocValuesFacetCounts}
+ */
+class FilteredSortedSetDocValuesFacetCounts extends SortedSetDocValuesFacetCounts {
+    private final TopDocs docs;
+    private final Filter filter;
+    private final IndexReader reader;
+    private final SortedSetDocValuesReaderState state;
+
+    public FilteredSortedSetDocValuesFacetCounts(DefaultSortedSetDocValuesReaderState state, FacetsCollector facetsCollector, Filter filter, TopDocs docs) throws IOException {
+        super(state, facetsCollector);
+        this.reader = state.origReader;
+        this.filter = filter;
+        this.docs = docs;
+        this.state = state;
+    }
+
+    @Override
+    public FacetResult getTopChildren(int topN, String dim, String... path) throws IOException {
+        FacetResult topChildren = super.getTopChildren(topN, dim, path);
+
+        LabelAndValue[] labelAndValues = topChildren.labelValues;
+
+        for (ScoreDoc scoreDoc : docs.scoreDocs) {
+            labelAndValues = filterFacet(scoreDoc.doc, dim, labelAndValues);
+        }
+
+        int childCount = labelAndValues.length;
+        Number value = 0;
+        for (LabelAndValue lv : labelAndValues) {
+            value = value.longValue() + lv.value.longValue();
+        }
+
+        return new FacetResult(dim, path, value, labelAndValues, childCount);
+    }
+
+    private LabelAndValue[] filterFacet(int docId, String dimension, LabelAndValue[] labelAndValues) throws IOException {
+        boolean filterd = false;
+        Map<String, Long> newValues = new HashMap<String, Long>();
+
+        Document document = reader.document(docId);
+        SortedSetDocValues docValues = state.getDocValues();
+        docValues.setDocument(docId);
+
+        // filter using doc values (avoiding requiring stored values)
+        if (!filter.isAccessible(document.getField(FieldNames.PATH).stringValue() + "/" + dimension)) {
+            filterd = true;
+            for (LabelAndValue lv : labelAndValues) {
+                long existingCount = lv.value.longValue();
+
+                BytesRef key = new BytesRef(FacetsConfig.pathToString(dimension, new String[]{lv.label}));
+                long l = docValues.lookupTerm(key);
+                if (l >= 0) {
+                    if (existingCount > 0) {
+                        newValues.put(lv.label, existingCount - 1);
+                    } else {
+                        if (newValues.containsKey(lv.label)) {
+                            newValues.remove(lv.label);
+                        }
+                    }
+                }
+            }
+        }
+        LabelAndValue[] filteredLVs;
+        if (filterd) {
+            filteredLVs = new LabelAndValue[newValues.size()];
+            int i = 0;
+            for (Map.Entry<String, Long> entry : newValues.entrySet()) {
+                filteredLVs[i] = new LabelAndValue(entry.getKey(), entry.getValue());
+                i++;
+            }
+        } else {
+            filteredLVs = labelAndValues;
+        }
+
+        return filteredLVs;
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/FilteredSortedSetDocValuesFacetCounts.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/NodeStateFacetsConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/NodeStateFacetsConfig.java?rev=1720726&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/NodeStateFacetsConfig.java (added)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/NodeStateFacetsConfig.java Fri Dec 18 08:01:17 2015
@@ -0,0 +1,48 @@
+/*
+ * 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.util;
+
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.lucene.facet.FacetsConfig;
+
+/**
+ * {@link FacetsConfig} persisted extension.
+ */
+class NodeStateFacetsConfig extends FacetsConfig {
+
+    private static final String MULTIVALUED = "multivalued";
+
+    private final NodeBuilder nodeBuilder;
+
+    NodeStateFacetsConfig(NodeBuilder nodeBuilder) {
+        this.nodeBuilder = nodeBuilder.child("config");
+        for (String child : this.nodeBuilder.getChildNodeNames()) {
+            super.setMultiValued(child, this.nodeBuilder.child(child).getProperty(MULTIVALUED).getValue(Type.BOOLEAN));
+        }
+    }
+
+    @Override
+    public synchronized void setMultiValued(String dimName, boolean v) {
+        super.setMultiValued(dimName, v);
+        if (v) {
+            nodeBuilder.child(dimName).setProperty(MULTIVALUED, true);
+        }
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/NodeStateFacetsConfig.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/package-info.java?rev=1720726&r1=1720725&r2=1720726&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/package-info.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/util/package-info.java Fri Dec 18 08:01:17 2015
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@Version("2.0.0")
+@Version("2.1.0")
 @Export(optional = "provide:=true")
 package org.apache.jackrabbit.oak.plugins.index.lucene.util;
 

Modified: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/FacetTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/FacetTest.java?rev=1720726&r1=1720725&r2=1720726&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/FacetTest.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/FacetTest.java Fri Dec 18 08:01:17 2015
@@ -38,22 +38,34 @@ import javax.jcr.query.RowIterator;
  */
 public class FacetTest extends AbstractQueryTest {
 
+    public static final String FACET_CONFING_NODE_PATH = "/oak:index/luceneGlobal/indexRules/nt:base/properties/allProps/facets";
+
     @Before
     protected void setUp() throws Exception {
         super.setUp();
-        Node node = superuser.getNode("/oak:index/luceneGlobal/indexRules/nt:base/properties/allProps");
-        node.setProperty(LuceneIndexConstants.PROP_FACET, true);
+        if (!superuser.nodeExists(FACET_CONFING_NODE_PATH)) {
+            Node node = superuser.getNode("/oak:index/luceneGlobal/indexRules/nt:base/properties/allProps");
+            Node facetConfig = node.addNode(LuceneIndexConstants.PROP_FACET, "nt:unstructured");
+            facetConfig.setProperty("enabled", true);
+            superuser.save();
+            superuser.refresh(true);
+        }
     }
 
     @After
     protected void tearDown() throws Exception {
-        superuser.getNode("/oak:index/luceneGlobal/indexRules/nt:base/properties/allProps").getProperty(LuceneIndexConstants.PROP_FACET).remove();
+        if (superuser.nodeExists(FACET_CONFING_NODE_PATH)) {
+            superuser.getNode(FACET_CONFING_NODE_PATH).remove();
+            superuser.save();
+            superuser.refresh(true);
+        }
         super.tearDown();
     }
 
     public void testFacetsNA() throws Exception {
-        Node node = superuser.getNode("/oak:index/luceneGlobal/indexRules/nt:base/properties/allProps");
-        node.setProperty(LuceneIndexConstants.PROP_FACET, false);
+        if (superuser.nodeExists(FACET_CONFING_NODE_PATH)) {
+            superuser.getNode(FACET_CONFING_NODE_PATH).remove();
+        }
         Session session = superuser;
         QueryManager qm = session.getWorkspace().getQueryManager();
         Node n1 = testRootNode.addNode("node1");