# Apache Lucene Migration Guide

## Changed SPI lookups for codecs and analysis changed (LUCENE-7873) ##

Due to serious problems with context class loaders in several frameworks
(OSGI, Java 9 Jigsaw), the lookup of Codecs, PostingsFormats, DocValuesFormats
and all analysis factories was changed to only inspect the current classloader
that defined the interface class (`lucene-core.jar`). Normal applications
should not encounter any issues with that change, because the application
classloader (unnamed module in Java 9) can load all SPIs from all JARs
from classpath.

For any code that relies on the old behaviour (e.g., certain web applications
or components in application servers) one can manually instruct the Lucene
SPI implementation to also inspect the context classloader. To do this,
add this code to the early startup phase of your application before any
Apache Lucene component is used:

    ClassLoader cl = Thread.currentThread().getContextClassLoader();
    // Codecs:
    PostingsFormat.reloadPostingsFormats(cl);
    DocValuesFormat.reloadDocValuesFormats(cl);
    Codec.reloadCodecs(cl);
    // Analysis:
    CharFilterFactory.reloadCharFilters(cl);
    TokenFilterFactory.reloadTokenFilters(cl);
    TokenizerFactory.reloadTokenizers(cl);

This code will reload all service providers from the given class loader
(in our case the context class loader). Of course, instead of specifying
the context class loader, it is receommended to use the application's main
class loader or the module class loader.

If you are migrating your project to Java 9 Jigsaw module system, keep in mind
that Lucene currently does not yet support `module-info.java` declarations of
service provider impls (`provides` statement). It is therefore recommended
to keep all of Lucene in one Uber-Module and not try to split Lucene into
several modules. As soon as Lucene will migrate to Java 9 as minimum
requirement, we will work on improving that.

For OSGI, the same applies. You have to create a bundle with all of Lucene for
SPI to work correctly.

## CustomAnalyzer resources (LUCENE-7883)##

Lucene no longer uses the context class loader when resolving resources in
CustomAnalyzer or ClassPathResourceLoader. Resources are only resolved
against Lucene's class loader by default. Please use another builder method
to change to a custom classloader.

## Query.hashCode and Query.equals are now abstract methods (LUCENE-7277)

Any custom query subclasses should redeclare equivalence relationship according
to the subclass's details. See code patterns used in existing core Lucene query
classes for details.

## CompressionTools removed (LUCENE-7322)

Per-field compression has been superseded by codec-level compression, which has
the benefit of being able to compress several fields, or even documents at once,
yielding better compression ratios. In case you would still like to compress on
top of the codec, you can do it on the application side by using the utility
classes from the java.util.zip package.

## Explanation.toHtml() removed (LUCENE-7360)

Clients wishing to render Explanations as HTML should implement their own
utilities for this.

## Similarity.coord and BooleanQuery.disableCoord removed (LUCENE-7369)

Coordination factors were a workaround for the fact that the ClassicSimilarity
does not have strong enough term frequency saturation. This causes disjunctions
to get better scores on documents that have many occurrences of a few query
terms than on documents that match most clauses, which is most of time
undesirable. The new BM25Similarity does not suffer from this problem since it
has better saturation for the contribution of the term frequency so the coord
factors have been removed from scores. Things now work as if coords were always
disabled when constructing boolean queries.

## Weight.getValueForNormalization() and Weight.normalize() removed (LUCENE-7368)

Query normalization's goal was to make scores comparable across queries, which
was only implemented by the ClassicSimilarity. Since ClassicSimilarity is not
the default similarity anymore, this functionality has been removed. Boosts are
now propagated through Query#createWeight.

## AnalyzingQueryParser removed (LUCENE-7355)

The functionality of AnalyzingQueryParser has been folded into the classic
QueryParser, which now passes terms through Analyzer#normalize when generating
queries.

## CommonQueryParserConfiguration.setLowerCaseExpandedTerms removed (LUCENE-7355)

This option has been removed as expanded terms are now normalized through
Analyzer#normalize.

## Cache key and close listener refactoring (LUCENE-7410)

The way to access cache keys and add close listeners has been refactored in
order to be less trappy. You should now use IndexReader.getReaderCacheHelper()
to have manage caches that take deleted docs and doc values updates into
account, and LeafReader.getCoreCacheHelper() to manage per-segment caches that
do not take deleted docs and doc values updates into account.

## Index-time boosts removal (LUCENE-6819)

Index-time boosts are not supported anymore. As a replacement, index-time
scoring factors should be indexed in a doc value field and combined with the
score at query time using FunctionScoreQuery for instance.

## Grouping collector refactoring (LUCENE-7701)

Groups are now defined by GroupSelector classes, making it easier to define new
types of groups.  Rather than having term or function specific collection
classes, FirstPassGroupingCollector, AllGroupsCollector and
AllGroupHeadsCollector are now concrete classes taking a GroupSelector.

SecondPassGroupingCollector is no longer specifically aimed at
collecting TopDocs for each group, but instead takes a GroupReducer that will
perform any type of reduction on the top groups collected on a first-pass.  To
reproduce the old behaviour of SecondPassGroupingCollector, you should instead
use TopGroupsCollector.

## Removed legacy numerics (LUCENE-7850)

Support for legacy numerics has been removed since legacy numerics had been
deprecated since Lucene 6.0. Points should be used instead, see
org.apache.lucene.index.PointValues for an introduction.

## TopDocs.totalHits is now a long (LUCENE-7872)

TopDocs.totalHits is now a long so that TopDocs instances can be used to
represent top hits that have more than 2B matches. This is necessary for the
case that multiple TopDocs instances are merged together with TopDocs#merge as
they might have more than 2B matches in total. However TopDocs instances
returned by IndexSearcher will still have a total number of hits which is less
than 2B since Lucene indexes are still bound to at most 2B documents, so it
can safely be casted to an int in that case.

## PrefixAwareTokenFilter and PrefixAndSuffixAwareTokenFilter removed
(LUCENE-7877)

Instead use ConcatentingTokenStream, which will allow for the use of custom
attributes.

## FieldValueQuery is renamed to DocValuesFieldExistsQuery (LUCENE-7899)

This query matches only documents that have a value for the specified doc
values field.

## RAMDirectory, RAMFile, RAMInputStream, RAMOutputStream are deprecated ##

This RAM-based directory implementation is an old piece of code that uses inefficient
thread synchronization primitives and can be confused as "faster" than the NIO-based
MMapDirectory. It is deprecated and scheduled for removal in future versions of 
Lucene. (LUCENE-8467, LUCENE-8438)

