You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by rm...@apache.org on 2011/03/31 22:13:23 UTC

svn commit: r1087430 - in /lucene/dev/trunk/solr: ./ src/common/org/apache/solr/common/util/ src/java/org/apache/solr/schema/ src/java/org/apache/solr/search/ src/test-files/solr/conf/ src/test/org/apache/solr/schema/

Author: rmuir
Date: Thu Mar 31 20:13:22 2011
New Revision: 1087430

URL: http://svn.apache.org/viewvc?rev=1087430&view=rev
Log:
SOLR-2338: improved per-field similarity integration into schema.xml

Added:
    lucene/dev/trunk/solr/src/java/org/apache/solr/schema/SimilarityProviderFactory.java   (with props)
    lucene/dev/trunk/solr/src/java/org/apache/solr/search/SolrSimilarityProvider.java   (with props)
    lucene/dev/trunk/solr/src/test/org/apache/solr/schema/CustomSimilarityProviderFactory.java   (with props)
    lucene/dev/trunk/solr/src/test/org/apache/solr/schema/MockConfigurableSimilarityProvider.java   (with props)
    lucene/dev/trunk/solr/src/test/org/apache/solr/schema/TestPerFieldSimilarity.java   (with props)
Modified:
    lucene/dev/trunk/solr/CHANGES.txt
    lucene/dev/trunk/solr/src/common/org/apache/solr/common/util/NamedList.java
    lucene/dev/trunk/solr/src/java/org/apache/solr/schema/FieldType.java
    lucene/dev/trunk/solr/src/java/org/apache/solr/schema/IndexSchema.java
    lucene/dev/trunk/solr/src/java/org/apache/solr/schema/SimilarityFactory.java
    lucene/dev/trunk/solr/src/test-files/solr/conf/schema.xml
    lucene/dev/trunk/solr/src/test/org/apache/solr/schema/CustomSimilarityFactory.java
    lucene/dev/trunk/solr/src/test/org/apache/solr/schema/IndexSchemaTest.java
    lucene/dev/trunk/solr/src/test/org/apache/solr/schema/MockConfigurableSimilarity.java

Modified: lucene/dev/trunk/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/CHANGES.txt?rev=1087430&r1=1087429&r2=1087430&view=diff
==============================================================================
--- lucene/dev/trunk/solr/CHANGES.txt (original)
+++ lucene/dev/trunk/solr/CHANGES.txt Thu Mar 31 20:13:22 2011
@@ -117,6 +117,9 @@ New Features
 * SOLR-2396: Add CollationField, which is much more efficient than 
   the Solr 3.x CollationKeyFilterFactory, and also supports 
   Locale-sensitive range queries. (rmuir)
+
+* SOLR-2338: Add support for using <similarity/> in a schema's fieldType,
+  for customizing scoring on a per-field basis. (hossman, yonik, rmuir)
   
 
 Optimizations

Modified: lucene/dev/trunk/solr/src/common/org/apache/solr/common/util/NamedList.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/common/org/apache/solr/common/util/NamedList.java?rev=1087430&r1=1087429&r2=1087430&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/common/org/apache/solr/common/util/NamedList.java (original)
+++ lucene/dev/trunk/solr/src/common/org/apache/solr/common/util/NamedList.java Thu Mar 31 20:13:22 2011
@@ -43,7 +43,7 @@ import java.io.Serializable;
  * by key, so ResponseWriters that output to a format such as JSON will normally
  * choose a data structure that allows order to be easily preserved in various
  * clients (i.e. not a straight map).
- * If access by key is more important, see {@link SimpleOrderedMap},
+ * If access by key is more important for serialization, see {@link SimpleOrderedMap},
  * or simply use a regular {@link Map}
  * </p>
  *
@@ -200,10 +200,14 @@ public class NamedList<T> implements Clo
   /**
    * Gets the value for the first instance of the specified name
    * found.
-   *
+   * <p>
+   * NOTE: this runs in linear time (it scans starting at the
+   * beginning of the list until it finds the first pair with
+   * the specified name).
    * @return null if not found or if the value stored was null.
    * @see #indexOf
    * @see #get(String,int)
+   * 
    */
   public T get(String name) {
     return get(name,0);
@@ -212,7 +216,10 @@ public class NamedList<T> implements Clo
   /**
    * Gets the value for the first instance of the specified name
    * found starting at the specified index.
-   *
+   * <p>
+   * NOTE: this runs in linear time (it scans starting at the
+   * specified position until it finds the first pair with
+   * the specified name).
    * @return null if not found or if the value stored was null.
    * @see #indexOf
    */
@@ -377,6 +384,11 @@ public class NamedList<T> implements Clo
     return iter;
   }
 
+  /** 
+   * NOTE: this runs in linear time (it scans starting at the
+   * beginning of the list until it finds the first pair with
+   * the specified name).
+   */
   public T remove(String name) {
     int idx = indexOf(name, 0);
     if(idx != -1) return remove(idx);

Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/schema/FieldType.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/schema/FieldType.java?rev=1087430&r1=1087429&r2=1087430&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/schema/FieldType.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/schema/FieldType.java Thu Mar 31 20:13:22 2011
@@ -25,6 +25,7 @@ import org.apache.lucene.document.Field;
 import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.Query;
+import org.apache.lucene.search.Similarity;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.search.TermQuery;
 import org.apache.lucene.search.TermRangeQuery;
@@ -503,6 +504,34 @@ public abstract class FieldType extends 
     throw e;
   }
 
+  /** @lucene.internal */
+  protected Similarity similarity;
+  
+  /**
+   * Gets the Similarity used when scoring fields of this type
+   * 
+   * <p>
+   * The default implementation returns null, which means this type
+   * has no custom similarity associated with it.
+   * </p>
+   * 
+   * This method exists to internally support SolrSimilarityProvider. 
+   * Custom application code interested in a field's Similarity should
+   * instead query via the searcher's SimilarityProvider.
+   * @lucene.internal
+   */
+  public Similarity getSimilarity() {
+    return similarity;
+  }
+  
+  /**
+   * Sets the Similarity used when scoring fields of this type
+   * @lucene.internal
+   */
+  public void setSimilarity(Similarity similarity) {
+    this.similarity = similarity;
+  }
+  
   /**
    * calls back to TextResponseWriter to write the field value
    */

Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/schema/IndexSchema.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/schema/IndexSchema.java?rev=1087430&r1=1087429&r2=1087430&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/schema/IndexSchema.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/schema/IndexSchema.java Thu Mar 31 20:13:22 2011
@@ -20,7 +20,9 @@ package org.apache.solr.schema;
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.search.DefaultSimilarity;
 import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Similarity;
 import org.apache.lucene.search.SimilarityProvider;
 import org.apache.lucene.queryParser.QueryParser;
 import org.apache.lucene.util.Version;
@@ -28,6 +30,7 @@ import org.apache.solr.common.ResourceLo
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.DOMUtil;
+import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.util.SystemIdResolver;
 import org.apache.solr.core.SolrConfig;
 import org.apache.solr.core.Config;
@@ -37,6 +40,7 @@ import org.apache.solr.analysis.TokenFil
 import org.apache.solr.analysis.TokenizerChain;
 import org.apache.solr.analysis.TokenizerFactory;
 import org.apache.solr.search.SolrQueryParser;
+import org.apache.solr.search.SolrSimilarityProvider;
 import org.apache.solr.util.plugin.AbstractPluginLoader;
 import org.apache.solr.util.plugin.SolrCoreAware;
 import org.w3c.dom.*;
@@ -185,19 +189,22 @@ public final class IndexSchema {
    */
   public Collection<SchemaField> getRequiredFields() { return requiredFields; }
 
-  private SimilarityFactory similarityFactory;
+  private SimilarityProviderFactory similarityProviderFactory;
 
   /**
-   * Returns the Similarity used for this index
+   * Returns the SimilarityProvider used for this index
    */
-  public SimilarityProvider getSimilarityProvider() { return similarityFactory.getSimilarityProvider(); }
+  public SimilarityProvider getSimilarityProvider() { return similarityProviderFactory.getSimilarityProvider(this); }
 
   /**
-   * Returns the SimilarityFactory used for this index
+   * Returns the SimilarityProviderFactory used for this index
    */
-  public SimilarityFactory getSimilarityFactory() { return similarityFactory; }
-
+  public SimilarityProviderFactory getSimilarityProviderFactory() { return similarityProviderFactory; }
 
+  private Similarity fallbackSimilarity;
+  
+  /** fallback similarity, in the case a field doesnt specify */
+  public Similarity getFallbackSimilarity() { return fallbackSimilarity; }
 
   /**
    * Returns the Analyzer used when indexing documents for this index
@@ -387,6 +394,11 @@ public final class IndexSchema {
           expression = "./analyzer[not(@type)] | ./analyzer[@type='index']";
           anode = (Node)xpath.evaluate(expression, node, XPathConstants.NODE);
           Analyzer analyzer = readAnalyzer(anode);
+          
+          // a custom similarity[Factory]
+          expression = "./similarity";
+          anode = (Node)xpath.evaluate(expression, node, XPathConstants.NODE);
+          Similarity similarity = readSimilarity(anode);
 
           if (queryAnalyzer==null) queryAnalyzer=analyzer;
           if (analyzer==null) analyzer=queryAnalyzer;
@@ -394,6 +406,9 @@ public final class IndexSchema {
             ft.setAnalyzer(analyzer);
             ft.setQueryAnalyzer(queryAnalyzer);
           }
+          if (similarity!=null) {
+            ft.setSimilarity(similarity);
+          }
           if (ft instanceof SchemaAware){
             schemaAware.add((SchemaAware) ft);
           }
@@ -491,36 +506,31 @@ public final class IndexSchema {
     // stuff it in a normal array for faster access
     dynamicFields = dFields.toArray(new DynamicField[dFields.size()]);
 
-
     Node node = (Node) xpath.evaluate("/schema/similarity", document, XPathConstants.NODE);
+    Similarity similarity = readSimilarity(node);
+    fallbackSimilarity = similarity == null ? new DefaultSimilarity() : similarity;
+
+    node = (Node) xpath.evaluate("/schema/similarityProvider", document, XPathConstants.NODE);
     if (node==null) {
-      similarityFactory = new SimilarityFactory() {
+      final SolrSimilarityProvider provider = new SolrSimilarityProvider(this);
+      similarityProviderFactory = new SimilarityProviderFactory() {
         @Override
-        public SimilarityProvider getSimilarityProvider() {
-          return IndexSearcher.getDefaultSimilarityProvider();
+        public SolrSimilarityProvider getSimilarityProvider(IndexSchema schema) {
+          return provider;
         }
       };
-      log.debug("using default similarity");
+      log.debug("using default similarityProvider");
     } else {
       final Object obj = loader.newInstance(((Element) node).getAttribute("class"));
-      if (obj instanceof SimilarityFactory) {
-        // configure a factory, get a similarity back
-        SolrParams params = SolrParams.toSolrParams(DOMUtil.childNodesToNamedList(node));
-        similarityFactory = (SimilarityFactory)obj;
-        similarityFactory.init(params);
-      } else {
-        // just like always, assume it's a SimilarityProvider and get a ClassCastException - reasonable error handling
-        similarityFactory = new SimilarityFactory() {
-          @Override
-          public SimilarityProvider getSimilarityProvider() {
-            return (SimilarityProvider) obj;
-          }
-        };
-      }
-      if (similarityFactory instanceof SchemaAware){
-        schemaAware.add((SchemaAware) similarityFactory);
+      // just like always, assume it's a SimilarityProviderFactory and get a ClassCastException - reasonable error handling
+      // configure a factory, get a similarity back
+      NamedList<?> args = DOMUtil.childNodesToNamedList(node);
+      similarityProviderFactory = (SimilarityProviderFactory)obj;
+      similarityProviderFactory.init(args);
+      if (similarityProviderFactory instanceof SchemaAware){
+        schemaAware.add((SchemaAware) similarityProviderFactory);
       }
-      log.debug("using similarity factory" + similarityFactory.getClass().getName());
+      log.debug("using similarityProvider factory" + similarityProviderFactory.getClass().getName());
     }
 
     node = (Node) xpath.evaluate("/schema/defaultSearchField/text()", document, XPathConstants.NODE);
@@ -750,6 +760,30 @@ public final class IndexSchema {
     return newArr;
   }
 
+  private Similarity readSimilarity(Node node) throws XPathExpressionException {
+    if (node==null) {
+      return null;
+    } else {
+      SimilarityFactory similarityFactory;
+      final Object obj = loader.newInstance(((Element) node).getAttribute("class"));
+      if (obj instanceof SimilarityFactory) {
+        // configure a factory, get a similarity back
+        SolrParams params = SolrParams.toSolrParams(DOMUtil.childNodesToNamedList(node));
+        similarityFactory = (SimilarityFactory)obj;
+        similarityFactory.init(params);
+      } else {
+        // just like always, assume it's a Similarity and get a ClassCastException - reasonable error handling
+        similarityFactory = new SimilarityFactory() {
+          @Override
+          public Similarity getSimilarity() {
+            return (Similarity) obj;
+          }
+        };
+      }
+      return similarityFactory.getSimilarity();
+    }
+  }
+
   //
   // <analyzer><tokenizer class="...."/><tokenizer class="...." arg="....">
   //

Modified: lucene/dev/trunk/solr/src/java/org/apache/solr/schema/SimilarityFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/schema/SimilarityFactory.java?rev=1087430&r1=1087429&r2=1087430&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/schema/SimilarityFactory.java (original)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/schema/SimilarityFactory.java Thu Mar 31 20:13:22 2011
@@ -16,7 +16,7 @@ package org.apache.solr.schema;
  * limitations under the License.
  */
 
-import org.apache.lucene.search.SimilarityProvider;
+import org.apache.lucene.search.Similarity;
 import org.apache.solr.common.params.SolrParams;
 
 public abstract class SimilarityFactory {
@@ -25,5 +25,5 @@ public abstract class SimilarityFactory 
   public void init(SolrParams params) { this.params = params; }
   public SolrParams getParams() { return params; }
 
-  public abstract SimilarityProvider getSimilarityProvider();
+  public abstract Similarity getSimilarity();
 }

Added: lucene/dev/trunk/solr/src/java/org/apache/solr/schema/SimilarityProviderFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/schema/SimilarityProviderFactory.java?rev=1087430&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/schema/SimilarityProviderFactory.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/schema/SimilarityProviderFactory.java Thu Mar 31 20:13:22 2011
@@ -0,0 +1,34 @@
+package org.apache.solr.schema;
+
+/**
+ * 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.
+ */
+
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.search.SolrSimilarityProvider;
+
+/**
+ * Expert: Factory to provide a {@link SolrSimilarityProvider}.
+ * <p>
+ * Usually you would implement this if you want to customize the
+ * scoring routines that are not field-specific, such as coord() and queryNorm(). 
+ * Most scoring customization happens in the fieldtype's Similarity
+ */
+public abstract class SimilarityProviderFactory {
+  public void init(NamedList<?> args) {}
+
+  public abstract SolrSimilarityProvider getSimilarityProvider(IndexSchema schema);
+}

Added: lucene/dev/trunk/solr/src/java/org/apache/solr/search/SolrSimilarityProvider.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/java/org/apache/solr/search/SolrSimilarityProvider.java?rev=1087430&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/java/org/apache/solr/search/SolrSimilarityProvider.java (added)
+++ lucene/dev/trunk/solr/src/java/org/apache/solr/search/SolrSimilarityProvider.java Thu Mar 31 20:13:22 2011
@@ -0,0 +1,56 @@
+package org.apache.solr.search;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.search.DefaultSimilarityProvider;
+import org.apache.lucene.search.Similarity;
+import org.apache.solr.schema.FieldType;
+import org.apache.solr.schema.IndexSchema;
+
+/**
+ * SimilarityProvider that uses the default Lucene implementation, unless
+ * otherwise specified by the fieldtype.
+ * <p>
+ * You can extend this class to customize the behavior of the parts
+ * of lucene's ranking system that are not field-specific, such as
+ * {@link #coord(int, int)} and {@link #queryNorm(float)}.
+ */
+public class SolrSimilarityProvider extends DefaultSimilarityProvider {
+  private final IndexSchema schema;
+
+  public SolrSimilarityProvider(IndexSchema schema) {
+    this.schema = schema;
+  }
+  
+  /** 
+   * Solr implementation delegates to the fieldtype's similarity.
+   * If this does not exist, uses the schema's default similarity.
+   */
+  // note: this is intentionally final, to maintain consistency with
+  // whatever is specified in the the schema!
+  @Override
+  public final Similarity get(String field) {
+    FieldType fieldType = schema.getFieldTypeNoEx(field);
+    if (fieldType == null) {
+      return schema.getFallbackSimilarity();
+    } else {
+      Similarity similarity = fieldType.getSimilarity();
+      return similarity == null ? schema.getFallbackSimilarity() : similarity;
+    }
+  }
+}

Modified: lucene/dev/trunk/solr/src/test-files/solr/conf/schema.xml
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/test-files/solr/conf/schema.xml?rev=1087430&r1=1087429&r2=1087430&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/test-files/solr/conf/schema.xml (original)
+++ lucene/dev/trunk/solr/src/test-files/solr/conf/schema.xml Thu Mar 31 20:13:22 2011
@@ -391,6 +391,32 @@
 
   <fieldType name="latLon" class="solr.LatLonType" subFieldType="double"/>
 
+  <!--  some per-field similarity examples -->
+  
+  <!--  specify a Similarity classname directly -->
+  <fieldType name="sim1" class="solr.TextField">
+    <analyzer>
+      <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+    </analyzer>
+    <similarity class="org.apache.lucene.misc.SweetSpotSimilarity"/>
+  </fieldType>
+
+  <!--  specify a Similarity factory -->  
+  <fieldType name="sim2" class="solr.TextField">
+    <analyzer>
+      <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+    </analyzer>
+    <similarity class="org.apache.solr.schema.CustomSimilarityFactory">
+      <str name="echo">is there an echo?</str>
+    </similarity>
+  </fieldType>
+  
+  <!-- don't specify any sim at all: get the default  -->
+  <fieldType name="sim3" class="solr.TextField">
+    <analyzer>
+      <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+    </analyzer>
+  </fieldType>
  </types>
 
 
@@ -496,6 +522,9 @@
    <field name="multiDefault" type="string" indexed="true" stored="true" default="muLti-Default" multiValued="true"/>
    <field name="intDefault" type="int" indexed="true" stored="true" default="42" multiValued="false"/>
 
+   <field name="sim1text" type="sim1" indexed="true" stored="true"/>
+   <field name="sim2text" type="sim2" indexed="true" stored="true"/>
+   <field name="sim3text" type="sim3" indexed="true" stored="true"/>
 
    <field name="tlong" type="tlong" indexed="true" stored="true" />
 
@@ -574,6 +603,10 @@
 
    <dynamicField name="*_mfacet" type="string" indexed="true" stored="false" multiValued="true" />
 
+   <!-- make sure custom sims work with dynamic fields -->
+   <dynamicField name="*_sim1" type="sim1" indexed="true" stored="true"/>
+   <dynamicField name="*_sim2" type="sim2" indexed="true" stored="true"/>
+   <dynamicField name="*_sim3" type="sim3" indexed="true" stored="true"/>
  </fields>
 
  <defaultSearchField>text</defaultSearchField>
@@ -607,12 +640,18 @@
    <!-- dynamic destination -->
    <copyField source="*_dynamic" dest="dynamic_*"/>
 
- <!-- Similarity is the scoring routine for each document vs a query.
-      A custom similarity may be specified here, but the default is fine
+ <!-- expert: SimilarityProvider contains scoring routines that are not field-specific,
+      such as coord() and queryNorm(). most scoring customization happens in the fieldtype.
+      A custom similarity provider may be specified here, but the default is fine
       for most applications.
  -->
- <similarity class="org.apache.solr.schema.CustomSimilarityFactory">
+ <similarityProvider class="org.apache.solr.schema.CustomSimilarityProviderFactory">
    <str name="echo">is there an echo?</str>
- </similarity>
+ </similarityProvider>
 
+ <!-- default similarity, unless otherwise specified by the fieldType
+  -->
+ <similarity class="org.apache.solr.schema.CustomSimilarityFactory">
+   <str name="echo">I am your default sim</str>
+ </similarity>
 </schema>

Modified: lucene/dev/trunk/solr/src/test/org/apache/solr/schema/CustomSimilarityFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/test/org/apache/solr/schema/CustomSimilarityFactory.java?rev=1087430&r1=1087429&r2=1087430&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/test/org/apache/solr/schema/CustomSimilarityFactory.java (original)
+++ lucene/dev/trunk/solr/src/test/org/apache/solr/schema/CustomSimilarityFactory.java Thu Mar 31 20:13:22 2011
@@ -16,11 +16,11 @@
  */
 package org.apache.solr.schema;
 
-import org.apache.lucene.search.SimilarityProvider;
+import org.apache.lucene.search.Similarity;
 
 public class CustomSimilarityFactory extends SimilarityFactory {
   @Override
-  public SimilarityProvider getSimilarityProvider() {
+  public Similarity getSimilarity() {
     return new MockConfigurableSimilarity(params.get("echo"));
   }
 }

Added: lucene/dev/trunk/solr/src/test/org/apache/solr/schema/CustomSimilarityProviderFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/test/org/apache/solr/schema/CustomSimilarityProviderFactory.java?rev=1087430&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/test/org/apache/solr/schema/CustomSimilarityProviderFactory.java (added)
+++ lucene/dev/trunk/solr/src/test/org/apache/solr/schema/CustomSimilarityProviderFactory.java Thu Mar 31 20:13:22 2011
@@ -0,0 +1,34 @@
+/**
+ * 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.solr.schema;
+
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.search.SolrSimilarityProvider;
+
+public class CustomSimilarityProviderFactory extends SimilarityProviderFactory {
+  String echoParam;
+ 
+  @Override
+  public void init(NamedList<?> args) {
+    echoParam = (String) args.get("echo");
+  }
+
+  @Override
+  public SolrSimilarityProvider getSimilarityProvider(IndexSchema schema) {
+    return new MockConfigurableSimilarityProvider(schema, echoParam);
+  }
+}

Modified: lucene/dev/trunk/solr/src/test/org/apache/solr/schema/IndexSchemaTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/test/org/apache/solr/schema/IndexSchemaTest.java?rev=1087430&r1=1087429&r2=1087430&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/test/org/apache/solr/schema/IndexSchemaTest.java (original)
+++ lucene/dev/trunk/solr/src/test/org/apache/solr/schema/IndexSchemaTest.java Thu Mar 31 20:13:22 2011
@@ -81,11 +81,11 @@ public class IndexSchemaTest extends Sol
   }
 
   @Test
-  public void testSimilarityFactory() {
+  public void testSimilarityProviderFactory() {
     SolrCore core = h.getCore();
-    SimilarityProvider similarity = core.getSchema().getSimilarityProvider();
-    assertTrue("wrong class", similarity instanceof MockConfigurableSimilarity);
-    assertEquals("is there an echo?", ((MockConfigurableSimilarity)similarity).getPassthrough());
+    SimilarityProvider similarityProvider = core.getSchema().getSimilarityProvider();
+    assertTrue("wrong class", similarityProvider instanceof MockConfigurableSimilarityProvider);
+    assertEquals("is there an echo?", ((MockConfigurableSimilarityProvider)similarityProvider).getPassthrough());
   }
   
   @Test

Modified: lucene/dev/trunk/solr/src/test/org/apache/solr/schema/MockConfigurableSimilarity.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/test/org/apache/solr/schema/MockConfigurableSimilarity.java?rev=1087430&r1=1087429&r2=1087430&view=diff
==============================================================================
--- lucene/dev/trunk/solr/src/test/org/apache/solr/schema/MockConfigurableSimilarity.java (original)
+++ lucene/dev/trunk/solr/src/test/org/apache/solr/schema/MockConfigurableSimilarity.java Thu Mar 31 20:13:22 2011
@@ -16,9 +16,9 @@
  */
 package org.apache.solr.schema;
 
-import org.apache.lucene.search.DefaultSimilarityProvider;
+import org.apache.lucene.search.DefaultSimilarity;
 
-public class MockConfigurableSimilarity extends DefaultSimilarityProvider {
+public class MockConfigurableSimilarity extends DefaultSimilarity {
   private String passthrough;
 
   public MockConfigurableSimilarity(String passthrough) {

Added: lucene/dev/trunk/solr/src/test/org/apache/solr/schema/MockConfigurableSimilarityProvider.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/test/org/apache/solr/schema/MockConfigurableSimilarityProvider.java?rev=1087430&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/test/org/apache/solr/schema/MockConfigurableSimilarityProvider.java (added)
+++ lucene/dev/trunk/solr/src/test/org/apache/solr/schema/MockConfigurableSimilarityProvider.java Thu Mar 31 20:13:22 2011
@@ -0,0 +1,32 @@
+/**
+ * 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.solr.schema;
+
+import org.apache.solr.search.SolrSimilarityProvider;
+
+public class MockConfigurableSimilarityProvider extends SolrSimilarityProvider {
+  private String passthrough;
+
+  public MockConfigurableSimilarityProvider(IndexSchema schema, String passthrough) {
+    super(schema);
+    this.passthrough = passthrough;
+  }
+
+  public String getPassthrough() {
+    return passthrough;
+  }
+}

Added: lucene/dev/trunk/solr/src/test/org/apache/solr/schema/TestPerFieldSimilarity.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/src/test/org/apache/solr/schema/TestPerFieldSimilarity.java?rev=1087430&view=auto
==============================================================================
--- lucene/dev/trunk/solr/src/test/org/apache/solr/schema/TestPerFieldSimilarity.java (added)
+++ lucene/dev/trunk/solr/src/test/org/apache/solr/schema/TestPerFieldSimilarity.java Thu Mar 31 20:13:22 2011
@@ -0,0 +1,106 @@
+package org.apache.solr.schema;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.misc.SweetSpotSimilarity;
+import org.apache.lucene.search.DefaultSimilarity;
+import org.apache.lucene.search.Similarity;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.search.SolrIndexSearcher;
+import org.apache.solr.util.RefCounted;
+import org.junit.BeforeClass;
+
+/**
+ * Tests per-field similarity support in the schema
+ */
+public class TestPerFieldSimilarity extends SolrTestCaseJ4 {
+
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    initCore("solrconfig.xml","schema.xml");
+  }
+  
+  /** test a field where the sim is specified directly */
+  public void testDirect() throws Exception {
+    SolrCore core = h.getCore();
+    RefCounted<SolrIndexSearcher> searcher = core.getSearcher();
+    Similarity sim = searcher.get().getSimilarityProvider().get("sim1text");
+    assertEquals(SweetSpotSimilarity.class, sim.getClass());
+    searcher.decref();
+  }
+  
+  /** ... and for a dynamic field */
+  public void testDirectDynamic() throws Exception {
+    SolrCore core = h.getCore();
+    RefCounted<SolrIndexSearcher> searcher = core.getSearcher();
+    Similarity sim = searcher.get().getSimilarityProvider().get("text_sim1");
+    assertEquals(SweetSpotSimilarity.class, sim.getClass());
+    searcher.decref();
+  }
+  
+  /** test a field where a configurable sim factory is defined */
+  public void testFactory() throws Exception {
+    SolrCore core = h.getCore();
+    RefCounted<SolrIndexSearcher> searcher = core.getSearcher();
+    Similarity sim = searcher.get().getSimilarityProvider().get("sim2text");
+    assertEquals(MockConfigurableSimilarity.class, sim.getClass());
+    assertEquals("is there an echo?", ((MockConfigurableSimilarity)sim).getPassthrough());
+    searcher.decref();
+  }
+  
+  /** ... and for a dynamic field */
+  public void testFactoryDynamic() throws Exception {
+    SolrCore core = h.getCore();
+    RefCounted<SolrIndexSearcher> searcher = core.getSearcher();
+    Similarity sim = searcher.get().getSimilarityProvider().get("text_sim2");
+    assertEquals(MockConfigurableSimilarity.class, sim.getClass());
+    assertEquals("is there an echo?", ((MockConfigurableSimilarity)sim).getPassthrough());
+    searcher.decref();
+  }
+  
+  /** test a field where no similarity is specified */
+  public void testDefaults() throws Exception {
+    SolrCore core = h.getCore();
+    RefCounted<SolrIndexSearcher> searcher = core.getSearcher();
+    Similarity sim = searcher.get().getSimilarityProvider().get("sim3text");
+    assertEquals(MockConfigurableSimilarity.class, sim.getClass());
+    assertEquals("I am your default sim", ((MockConfigurableSimilarity)sim).getPassthrough());
+    searcher.decref();
+  }
+  
+  /** ... and for a dynamic field */
+  public void testDefaultsDynamic() throws Exception {
+    SolrCore core = h.getCore();
+    RefCounted<SolrIndexSearcher> searcher = core.getSearcher();
+    Similarity sim = searcher.get().getSimilarityProvider().get("text_sim3");
+    assertEquals(MockConfigurableSimilarity.class, sim.getClass());
+    assertEquals("I am your default sim", ((MockConfigurableSimilarity)sim).getPassthrough());
+    searcher.decref();
+  }
+  
+  /** test a field that does not exist */
+  public void testNonexistent() throws Exception {
+    SolrCore core = h.getCore();
+    RefCounted<SolrIndexSearcher> searcher = core.getSearcher();
+    Similarity sim = searcher.get().getSimilarityProvider().get("sdfdsfdsfdswr5fsdfdsfdsfs");
+    assertEquals(MockConfigurableSimilarity.class, sim.getClass());
+    assertEquals("I am your default sim", ((MockConfigurableSimilarity)sim).getPassthrough());
+    searcher.decref();
+  }
+}