All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.solr.search.similarities.SchemaSimilarityFactory Maven / Gradle / Ivy

There is a newer version: 9.7.0
Show newest version
/*
 * 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.search.similarities;

import org.apache.lucene.search.similarities.BM25Similarity;
import org.apache.lucene.search.similarities.PerFieldSimilarityWrapper;
import org.apache.lucene.search.similarities.Similarity;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.core.SolrCore;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.SimilarityFactory;
import org.apache.solr.util.plugin.SolrCoreAware;

/**
 * SimilarityFactory that returns a global {@link PerFieldSimilarityWrapper} that
 * delegates to the field type, if it's configured. For field types that do not have a 
 * Similarity explicitly configured, the global Similarity will use per
 * fieldtype defaults -- either based on an explicitly configured defaultSimFromFieldType
 *  a sensible default:
 *
 * 
    *
  • luceneMatchVersion >= 8.0 = {@link BM25Similarity} *
* *

The defaultSimFromFieldType option accepts the name of any fieldtype, and uses * whatever Similarity is explicitly configured for that fieldType as the default for * all other field types. For example: * *

 *   <similarity class="solr.SchemaSimilarityFactory" >
 *     <str name="defaultSimFromFieldType">type-using-custom-dfr</str>
 *   </similarity>
 *   ...
 *   <fieldType name="type-using-custom-dfr" class="solr.TextField">
 *     ...
 *     <similarity class="solr.DFRSimilarityFactory">
 *       <str name="basicModel">I(F)</str>
 *       <str name="afterEffect">B</str>
 *       <str name="normalization">H3</str>
 *       <float name="mu">900</float>
 *     </similarity>
 *   </fieldType>
 * 
* *

In the example above, any fieldtypes that do not define their own </similarity/> * will use the Similarity configured for the type-using-custom-dfr * . * *

NOTE: Users should be aware that even when this factory uses a single default * Similarity for some or all fields in a Query, the behavior can be inconsistent with the * behavior of explicitly configuring that same Similarity globally, because of * differences in how some multi-field / multi-clause behavior is defined in * PerFieldSimilarityWrapper. * * @see FieldType#getSimilarity */ public class SchemaSimilarityFactory extends SimilarityFactory implements SolrCoreAware { private static final String INIT_OPT = "defaultSimFromFieldType"; private String defaultSimFromFieldType; // set by init, if null use sensible implicit default private volatile SolrCore core; // set by inform(SolrCore) private volatile Similarity similarity; // lazy instantiated @Override public void inform(SolrCore core) { this.core = core; } @Override public void init(SolrParams args) { defaultSimFromFieldType = args.get(INIT_OPT, null); super.init(args); } @Override public Similarity getSimilarity() { if (null == core) { throw new IllegalStateException( "SchemaSimilarityFactory can not be used until SolrCoreAware.inform has been called"); } if (null == similarity) { // Need to instantiate lazily, can't do this in inform(SolrCore) because of chicken/egg // circular initialization hell with core.getLatestSchema() to lookup defaultSimFromFieldType Similarity defaultSim = null; if (null == defaultSimFromFieldType) { // nothing configured, choose a sensible implicit default... defaultSim = new BM25Similarity(); } else { FieldType defSimFT = core.getLatestSchema().getFieldTypeByName(defaultSimFromFieldType); if (null == defSimFT) { throw new SolrException( ErrorCode.SERVER_ERROR, "SchemaSimilarityFactory configured with " + INIT_OPT + "='" + defaultSimFromFieldType + "' but that does not exist"); } defaultSim = defSimFT.getSimilarity(); if (null == defaultSim) { throw new SolrException( ErrorCode.SERVER_ERROR, "SchemaSimilarityFactory configured with " + INIT_OPT + "='" + defaultSimFromFieldType + "' but that does not define a "); } } similarity = new SchemaSimilarity(defaultSim); } return similarity; } private class SchemaSimilarity extends PerFieldSimilarityWrapper { private Similarity defaultSimilarity; public SchemaSimilarity(Similarity defaultSimilarity) { this.defaultSimilarity = defaultSimilarity; } @Override public Similarity get(String name) { FieldType fieldType = core.getLatestSchema().getFieldTypeNoEx(name); if (fieldType == null) { return defaultSimilarity; } else { Similarity similarity = fieldType.getSimilarity(); return similarity == null ? defaultSimilarity : similarity; } } @Override public String toString() { return "SchemaSimilarity. Default: " + ((get("") == null) ? "null" : get("").toString()); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy