Apache Lucene.NET 4.8.0 Migration Guide
.NET API Conventions
Several Java conventions were replaced with their .NET counterparts:
Classes suffixed with
Comparatorare now suffixed withComparer.Most iterator classes were converted to .NET enumerators.
Instead of
Iterator(), callGetEnumerator()(in some cases, it may beGetIterator()).Instead of
HasNext(), callMoveNext()however note that this will advance the position of the enumerator.Instead of
Next()the return value can be retrieved from theCurrentproperty after callingMoveNext().
Classes and members that include numeric type names now use the language-agnostic .NET name. For example:
Instead of
ShortorGetShort()useInt16orGetInt16().Instead of
IntegerorGetInteger()useInt32orGetInt32().Instead of
LongorGetLong()useInt64orGetInt64().Instead of
FloatuseSingle. Note thatLucene.Net.Queries.Function.ValueSources.SingleFunctionwas renamedLucene.Net.Queries.Function.ValueSources.SingularFunctionto distinguish it from theSystem.Singledata type.
For collections, the
Sizeproperty is now namedCount.For arrays and files, the
Sizeproperty is now namedLength.For
IndexInputandIndexOutputsubclasses,GetFilePointer()method has been changed to aPositionproperty to matchSystem.IO.FileStream.Position.Some classes, enums, and interfaces have been de-nested from their original Lucene location to make them easier to find when using Intellisense.
Some methods were lacking a verb, so the verb
Getwas added to make the method's function more clear. For example, instead ofAnalysis.TokenStream()we now haveAnalysis.GetTokenStream().
Four-dimensional enumerations
Flexible indexing changed the low level fields/terms/docs/positions enumeration APIs. Here are the major changes:
Terms are now binary in nature (arbitrary
byte[]), represented by theBytesRefclass (which provides an offset + length "slice" into an existingbyte[]).Fields are separately enumerated (
Fields.GetEnumerator()) from the terms within each field (TermEnum). So instead of this:TermEnum termsEnum = ...; while (termsEnum.Next()) { Term t = termsEnum.Term; Console.WriteLine("field=" + t.Field + "; text=" + t.Text); }Do this:
foreach (string field in fields) { Terms terms = fields.GetTerms(field); TermsEnum termsEnum = terms.GetEnumerator(); BytesRef text; while(termsEnum.MoveNext()) { Console.WriteLine("field=" + field + "; text=" + termsEnum.Current.Utf8ToString()); } }TermDocsis renamed toDocsEnum. Instead of this:while (td.Next()) { int doc = td.Doc; ... }do this:
int doc; while ((doc = td.Next()) != DocsEnum.NO_MORE_DOCS) { ... }Instead of this:
if (td.SkipTo(target)) { int doc = td.Doc; ... }do this:
if ((doc = td.Advance(target)) != DocsEnum.NO_MORE_DOCS) { ... }TermPositionsis renamed toDocsAndPositionsEnum, and no longer extends the docs only enumerator (DocsEnum).Deleted docs are no longer implicitly filtered from docs/positions enums. Instead, you pass a
IBitsSkipDocs(set bits are skipped) when obtaining the enums. Also, you can now ask a reader for its deleted docs.The docs/positions enums cannot seek to a term. Instead,
TermsEnumis able to seek, and then you request the docs/positions enum from thatTermsEnum.TermsEnum's seek method returns more information. So instead of this:Term t; TermEnum termEnum = reader.Terms(t); if (t.Equals(termEnum.Term)) { ... }do this:
TermsEnum termsEnum = ...; BytesRef text; if (termsEnum.Seek(text) == TermsEnum.SeekStatus.FOUND) { ... }SeekStatusalso containsEND(enumerator is done) andNOT_FOUND(term was not found but enumerator is now positioned to the next term).TermsEnumhas anOrdproperty, returning the long numeric ordinal (ie, first term is 0, next is 1, and so on) for the term it's not positioned to. There is also a corresponding Seek(long ord) method. Note that these members are optional; in particular theMultiFieldsTermsEnumdoes not implement them.How you obtain the enums has changed. The primary entry point is the
Fieldsclass. If you know your reader is a single segment reader, do this:Fields fields = reader.Fields(); if (fields != null) { ... }If the reader might be multi-segment, you must do this:
Fields fields = MultiFields.GetFields(reader); if (fields != null) { ... }The fields may be
null(eg if the reader has no fields).
Note that theMultiFieldsapproach entails a performance hit onMultiReaders, as it must merge terms/docs/positions on the fly. It's generally better to instead get the sequential readers (useLucene.Net.Util.ReaderUtil) and then step through those readers yourself, if you can (this is how Lucene drives searches).
If you pass aSegmentReadertoMultiFields.GetFields()it will simply returnreader.GetFields(), so there is no performance hit in that case.
Once you have a non-nullFieldsyou can do this:Terms terms = fields.GetTerms("field"); if (terms != null) { ... }The terms may be
null(eg if the field does not exist).
Once you have a non-null terms you can get an enum like this:TermsEnum termsEnum = terms.GetIterator();The returned
TermsEnumwill not benull.
You can then .Next() through the TermsEnum, or Seek. If you want aDocsEnum, do this:IBits liveDocs = reader.GetLiveDocs(); DocsEnum docsEnum = null; docsEnum = termsEnum.Docs(liveDocs, docsEnum, needsFreqs);You can pass in a prior
DocsEnumand it will be reused if possible.
Likewise forDocsAndPositionsEnum.
IndexReaderhas several sugar methods (which just go through the above steps, under the hood). Instead of:Term t; TermDocs termDocs = reader.TermDocs; termDocs.Seek(t);do this:
Term t; DocsEnum docsEnum = reader.GetTermDocsEnum(t);Likewise for
DocsAndPositionsEnum.
LUCENE-2380: FieldCache.GetStrings/Index --> FieldCache.GetDocTerms/Index
The field values returned when sorting by
SortField.STRINGare nowBytesRef. You can callvalue.Utf8ToString()to convert back to string, if necessary.In
FieldCache,GetStrings(returningstring[]) has been replaced withGetTerms(returning aBinaryDocValuesinstance).BinaryDocValuesprovides aGetmethod, taking adocIDand aBytesRefto fill (which must not benull), and it fills it in with the reference to the bytes for that term.
If you had code like this before:string[] values = FieldCache.DEFAULT.GetStrings(reader, field); ... string aValue = values[docID];you can do this instead:
BinaryDocValues values = FieldCache.DEFAULT.GetTerms(reader, field); ... BytesRef term = new BytesRef(); values.Get(docID, term); string aValue = term.Utf8ToString();Note however that it can be costly to convert to
String, so it's better to work directly with theBytesRef.Similarly, in
FieldCache, GetStringIndex (returning aStringIndexinstance, with direct arraysint[]order andString[]lookup) has been replaced withGetTermsIndex(returning aSortedDocValuesinstance).SortedDocValuesprovides theGetOrd(int docID)method to lookup the int order for a document,LookupOrd(int ord, BytesRef result)to lookup the term from a given order, and the sugar methodGet(int docID, BytesRef result)which internally callsGetOrdand thenLookupOrd.
If you had code like this before:StringIndex idx = FieldCache.DEFAULT.GetStringIndex(reader, field); ... int ord = idx.order[docID]; String aValue = idx.lookup[ord];you can do this instead:
DocTermsIndex idx = FieldCache.DEFAULT.GetTermsIndex(reader, field); ... int ord = idx.GetOrd(docID); BytesRef term = new BytesRef(); idx.LookupOrd(ord, term); string aValue = term.Utf8ToString();Note however that it can be costly to convert to
String, so it's better to work directly with theBytesRef.
DocTermsIndexalso has aGetTermsEnum()method, which returns an iterator (TermsEnum) over the term values in the index (ie, iterates ord = 0..NumOrd-1).FieldComparator.StringComparatorLocalehas been removed. (it was very CPU costly since it does not compare using indexed collation keys; use CollationKeyFilter for better performance), since it convertsBytesRef->Stringon the fly.FieldComparator.StringOrdValComparatorhas been renamed toFieldComparer.TermOrdValComparer, and now usesBytesReffor its values. Likewise forStringValComparator, renamed toTermValComparer. This means when sorting bySortField.STRINGorSortField.STRING_VAL(or directly invoking these comparers) the values returned in theFieldDoc.Fieldsarray will beBytesRefnotString. You can call the.Utf8ToString()method on theBytesRefinstances, if necessary.
LUCENE-2600: IndexReaders are now read-only
Instead of IndexReader.IsDeleted(int n), do this:
using Lucene.Net.Util;
using Lucene.Net.Index;
IBits liveDocs = MultiFields.GetLiveDocs(indexReader);
if (liveDocs != null && !liveDocs.Get(docID))
{
// document is deleted...
}
LUCENE-2858, LUCENE-3733: IndexReader --> AtomicReader/CompositeReader/DirectoryReader refactoring
The abstract class IndexReader has been
refactored to expose only essential methods to access stored fields
during display of search results. It is no longer possible to retrieve
terms or postings data from the underlying index, not even deletions are
visible anymore. You can still pass IndexReader as constructor parameter
to IndexSearcher and execute your searches; Lucene will automatically
delegate procedures like query rewriting and document collection atomic
subreaders.
If you want to dive deeper into the index and want to write own queries,
take a closer look at the new abstract sub-classes AtomicReader and
CompositeReader:
AtomicReader instances are now the only source of Terms, Postings,
DocValues and FieldCache. Queries are forced to execute on an AtomicReader on a per-segment basis and FieldCaches are keyed by
AtomicReaders.
Its counterpart CompositeReader exposes a utility method to retrieve
its composites. But watch out, composites are not necessarily atomic.
Next to the added type-safety we also removed the notion of
index-commits and version numbers from the abstract IndexReader, the
associations with IndexWriter were pulled into a specialized
DirectoryReader. To open Directory-based indexes use
DirectoryReader.Open(), the corresponding method in IndexReader is now
deprecated for easier migration. Only DirectoryReader supports commits,
versions, and reopening with OpenIfChanged(). Terms, postings,
docvalues, and norms can from now on only be retrieved using
AtomicReader; DirectoryReader and MultiReader extend CompositeReader,
only offering stored fields and access to the sub-readers (which may be
composite or atomic).
If you have more advanced code dealing with custom Filters, you might
have noticed another new class hierarchy in Lucene (see LUCENE-2831):
IndexReaderContext with corresponding Atomic-/CompositeReaderContext.
The move towards per-segment search Lucene 2.9 exposed lots of custom
Querys and Filters that couldn't handle it. For example, some Filter
implementations expected the IndexReader passed in is identical to the
IndexReader passed to IndexSearcher with all its advantages like
absolute document IDs etc. Obviously this "paradigm-shift" broke lots of
applications and especially those that utilized cross-segment data
structures (like Apache Solr).
In Lucene 4.0, we introduce IndexReaderContexts "searcher-private"
reader hierarchy. During Query or Filter execution Lucene no longer
passes raw readers down Querys, Filters or Collectors; instead
components are provided an AtomicReaderContext (essentially a hierarchy
leaf) holding relative properties like the document-basis in relation to
the top-level reader. This allows Querys and Filter to build up logic
based on document IDs, albeit the per-segment orientation.
There are still valid use-cases where top-level readers ie. "atomic
views" on the index are desirable. Let say you want to iterate all terms
of a complete index for auto-completion or faceting, Lucene provides
utility wrappers like SlowCompositeReaderWrapper (LUCENE-2597) emulating
an AtomicReader. Note: using "atomicity emulators" can cause serious
slowdowns due to the need to merge terms, postings, DocValues, and
FieldCache, use them with care!
LUCENE-4306: GetSequentialSubReaders(), ReaderUtil.Gather()
The method IndexReader.GetSequentialSubReaders() was moved to CompositeReader
(see LUCENE-2858, LUCENE-3733) and made protected. It is solely used by CompositeReader itself to build its reader tree. To get all atomic leaves
of a reader, use IndexReader.Leaves, which also provides the doc base
of each leave. Readers that are already atomic return itself as leaf with
doc base 0. To emulate Lucene 3.x GetSequentialSubReaders(),
use Context.Children.
LUCENE-2413,LUCENE-3396: Analyzer package changes Lucene's core and contrib analyzers, along with Solr's analyzers,
were consolidated into lucene/analysis. During the refactoring some
package names have changed, and ReusableAnalyzerBase was renamed to
Analyzer:
Lucene.Net.Analysis.KeywordAnalyzer->Lucene.Net.Analysis.Core.KeywordAnalyzerLucene.Net.Analysis.KeywordTokenizer->Lucene.Net.Analysis.Core.KeywordTokenizerLucene.Net.Analysis.LetterTokenizer->Lucene.Net.Analysis.Core.LetterTokenizerLucene.Net.Analysis.LowerCaseFilter->Lucene.Net.Analysis.Core.LowerCaseFilterLucene.Net.Analysis.LowerCaseTokenizer->Lucene.Net.Analysis.Core.LowerCaseTokenizerLucene.Net.Analysis.SimpleAnalyzer->Lucene.Net.Analysis.Core.SimpleAnalyzerLucene.Net.Analysis.StopAnalyzer->Lucene.Net.Analysis.Core.StopAnalyzerLucene.Net.Analysis.StopFilter->Lucene.Net.Analysis.Core.StopFilterLucene.Net.Analysis.WhitespaceAnalyzer->Lucene.Net.Analysis.Core.WhitespaceAnalyzerLucene.Net.Analysis.WhitespaceTokenizer->Lucene.Net.Analysis.Core.WhitespaceTokenizerLucene.Net.Analysis.PorterStemFilter->Lucene.Net.Analysis.En.PorterStemFilterLucene.Net.Analysis.ASCIIFoldingFilter->Lucene.Net.Analysis.Miscellaneous.ASCIIFoldingFilterLucene.Net.Analysis.ISOLatin1AccentFilter->Lucene.Net.Analysis.Miscellaneous.ISOLatin1AccentFilterLucene.Net.Analysis.KeywordMarkerFilter->Lucene.Net.Analysis.Miscellaneous.KeywordMarkerFilterLucene.Net.Analysis.LengthFilter->Lucene.Net.Analysis.Miscellaneous.LengthFilterLucene.Net.Analysis.PerFieldAnalyzerWrapper->Lucene.Net.Analysis.Miscellaneous.PerFieldAnalyzerWrapperLucene.Net.Analysis.TeeSinkTokenFilter->Lucene.Net.Analysis.Sinks.TeeSinkTokenFilterLucene.Net.Analysis.CharFilter->Lucene.Net.Analysis.CharFilter.CharFilterLucene.Net.Analysis.BaseCharFilter->Lucene.Net.Analysis.CharFilter.BaseCharFilterLucene.Net.Analysis.MappingCharFilter->Lucene.Net.Analysis.CharFilter.MappingCharFilterLucene.Net.Analysis.NormalizeCharMap->Lucene.Net.Analysis.CharFilter.NormalizeCharMapLucene.Net.Analysis.CharArraySet->Lucene.Net.Analysis.Util.CharArraySetLucene.Net.Analysis.CharArrayMap->Lucene.Net.Analysis.Util.CharArrayMapLucene.Net.Analysis.ReusableAnalyzerBase->Lucene.Net.Analysis.AnalyzerLucene.Net.Analysis.StopwordAnalyzerBase->Lucene.Net.Analysis.Util.StopwordAnalyzerBaseLucene.Net.Analysis.WordListLoader->Lucene.Net.Analysis.Util.WordListLoaderLucene.Net.Analysis.CharTokenizer->Lucene.Net.Analysis.Util.CharTokenizerLucene.Net.Util.CharacterUtils->Lucene.Net.Analysis.Util.CharacterUtils
LUCENE-2514: Collators
The option to use a Collator's order (instead of binary order) for
sorting and range queries has been moved to lucene/queries.
The Collated TermRangeQuery/Filter has been moved to SlowCollatedTermRangeQuery/Filter,
and the collated sorting has been moved to SlowCollatedStringComparer.
Note: this functionality isn't very scalable and if you are using it, consider indexing collation keys with the collation support in the analysis module instead.
To perform collated range queries, use the collating analyzer: ICUCollationKeyAnalyzer, and set qp.AnalyzeRangeTerms = true.
TermRangeQuery and TermRangeFilter now work purely on bytes. Both have helper factory methods
(NewStringRange) similar to the NumericRange API, to easily perform range queries on Strings.
LUCENE-2883: ValueSource changes
Lucene's Lucene.Net.Search.Function.ValueSource based functionality, was consolidated
into Lucene.Net/Lucene.Net.Queries along with Solr's similar functionality. The following classes were moved:
Lucene.Net.Search.Function.CustomScoreQuery->Lucene.Net.Queries.CustomScoreQueryLucene.Net.Search.Function.CustomScoreProvider->Lucene.Net.Queries.CustomScoreProviderLucene.Net.Search.Function.NumericIndexDocValueSource->Lucene.Net.Queries.Function.ValueSource.NumericIndexDocValueSource
The following lists the replacement classes for those removed:
Lucene.Net.Search.Function.DocValues->Lucene.Net.Queries.Function.DocValuesLucene.Net.Search.Function.FieldCacheSource->Lucene.Net.Queries.Function.ValueSources.FieldCacheSourceLucene.Net.Search.Function.FieldScoreQuery->Lucene.Net.Queries.Function.FunctionQueryLucene.Net.Search.Function.FloatFieldSource->Lucene.Net.Queries.Function.ValueSources.FloatFieldSourceLucene.Net.Search.Function.IntFieldSource->Lucene.Net.Queries.Function.ValueSources.IntFieldSourceLucene.Net.Search.Function.OrdFieldSource->Lucene.Net.Queries.Function.ValueSources.OrdFieldSourceLucene.Net.Search.Function.ReverseOrdFieldSource->Lucene.Net.Queries.Function.ValueSources.ReverseOrdFieldSourceLucene.Net.Search.Function.ShortFieldSource->Lucene.Net.Queries.Function.ValueSources.ShortFieldSourceLucene.Net.Search.Function.ValueSource->Lucene.Net.Queries.Function.ValueSourceLucene.Net.Search.Function.ValueSourceQuery->Lucene.Net.Queries.Function.FunctionQuery
DocValues are now named FunctionValues, to not confuse with Lucene's per-document values.
LUCENE-2392: Enable flexible scoring
The existing Similarity API is now TFIDFSimilarity, if you were extending
Similarity before, you should likely extend this instead.
Weight.Normalize() no longer takes a norm value that incorporates the top-level
boost from outer queries such as BooleanQuery, instead it takes 2 parameters,
the outer boost (topLevelBoost) and the norm. Weight.SumOfSquaredWeights has
been renamed to Weight.GetValueForNormalization().
The ScorePayload() method now takes a BytesRef. It is never null.
LUCENE-3283: Query parsers moved to separate module
Lucene's core Lucene.Net.QueryParsers query parsers have been consolidated into lucene/queryparser,
where other QueryParsers from the codebase will also be placed. The following classes were moved:
Lucene.Net.QueryParsers.CharStream->Lucene.Net.QueryParsers.Classic.CharStreamLucene.Net.QueryParsers.FastCharStream->Lucene.Net.QueryParsers.Classic.FastCharStreamLucene.Net.QueryParsers.MultiFieldQueryParser->Lucene.Net.QueryParsers.Classic.MultiFieldQueryParserLucene.Net.QueryParsers.ParseException->Lucene.Net.QueryParsers.Classic.ParseExceptionLucene.Net.QueryParsers.QueryParser->Lucene.Net.QueryParsers.Classic.QueryParserLucene.Net.QueryParsers.QueryParserBase->Lucene.Net.QueryParsers.Classic.QueryParserBaseLucene.Net.QueryParsers.QueryParserConstants->Lucene.Net.QueryParsers.Classic.QueryParserConstantsLucene.Net.QueryParsers.QueryParserTokenManager->Lucene.Net.QueryParsers.Classic.QueryParserTokenManagerLucene.Net.QueryParsers.QueryParserToken->Lucene.Net.QueryParsers.Classic.TokenLucene.Net.QueryParsers.QueryParserTokenMgrError->Lucene.Net.QueryParsers.Classic.TokenMgrError
LUCENE-2308, LUCENE-3453: Separate IndexableFieldType from Field instances
With this change, the indexing details (indexed, tokenized, norms,
indexOptions, stored, etc.) are moved into a separate FieldType
instance (rather than being stored directly on the Field).
This means you can create the FieldType instance once, up front, for a given field, and then re-use that instance whenever you instantiate the Field.
Certain field types are pre-defined since they are common cases:
StringField: indexes aStringvalue as a single token (ie, does not tokenize). This field turns off norms and indexes only doc IDS (does not index term frequency nor positions). This field does not store its value, but exposesTYPE_STOREDas well.TextField: indexes and tokenizes aString,ReaderorTokenStreamvalue, without term vectors. This field does not store its value, but exposesTYPE_STOREDas well.StoredField: field that stores its valueDocValuesField: indexes the value as aDocValuesfieldNumericField: indexes the numeric value so thatNumericRangeQuerycan be used at search-time.
If your usage fits one of those common cases you can simply
instantiate the above class. If you need to store the value, you can
add a separate StoredField to the document, or you can use
TYPE_STORED for the field:
Field f = new Field("field", "value", StringField.TYPE_STORED);
Alternatively, if an existing type is close to what you want but you need to make a few changes, you can copy that type and make changes:
FieldType bodyType = new FieldType(TextField.TYPE_STORED)
{
StoreTermVectors = true
};
You can of course also create your own FieldType from scratch:
FieldType t = new FieldType
{
Indexed = true,
Stored = true,
OmitNorms = true,
IndexOptions = IndexOptions.DOCS_AND_FREQS
};
t.Freeze();
FieldType has a Freeze() method to prevent further changes.
There is also a deprecated transition API, providing the same Index,
Store, TermVector enums from 3.x, and Field constructors taking these
enums.
When migrating from the 3.x API, if you did this before:
new Field("field", "value", Field.Store.NO, Field.Indexed.NOT_ANALYZED_NO_NORMS)
you can now do this:
new StringField("field", "value")
(though note that StringField indexes DOCS_ONLY).
If instead the value was stored:
new Field("field", "value", Field.Store.YES, Field.Indexed.NOT_ANALYZED_NO_NORMS)
you can now do this:
new Field("field", "value", TextField.TYPE_STORED)
If you didn't omit norms:
new Field("field", "value", Field.Store.YES, Field.Indexed.NOT_ANALYZED)
you can now do this:
FieldType ft = new FieldType(TextField.TYPE_STORED)
{
OmitNorms = false
};
new Field("field", "value", ft)
If you did this before (value can be String or TextReader):
new Field("field", value, Field.Store.NO, Field.Indexed.ANALYZED)
you can now do this:
new TextField("field", value, Field.Store.NO)
If instead the value was stored:
new Field("field", value, Field.Store.YES, Field.Indexed.ANALYZED)
you can now do this:
new TextField("field", value, Field.Store.YES)
If in addition you omit norms:
new Field("field", value, Field.Store.YES, Field.Indexed.ANALYZED_NO_NORMS)
you can now do this:
FieldType ft = new FieldType(TextField.TYPE_STORED)
{
OmitNorms = true
};
new Field("field", value, ft)
If you did this before (bytes is a byte[]):
new Field("field", bytes)
you can now do this:
new StoredField("field", bytes)
If you previously used the setter of Document.Boost, you must now pre-multiply
the document boost into each Field.Boost. If you have a
multi-valued field, you should do this only for the first Field
instance (ie, subsequent Field instance sharing the same field name
should only include their per-field boost and not the document level
boost) as the boost for multi-valued field instances are multiplied
together by Lucene.
Other changes
LUCENE-2674: A new
IdfExplainmethod was added toSimilarity(which is nowTFIDFSimilarity), that accepts an incoming docFreq. If you subclassTFIDFSimilarity, make sure you also override this method on upgrade, otherwise your customizations won't run for certainMultiTermQuerys.LUCENE-2691: The near-real-time API has moved from
IndexWritertoDirectoryReader. Instead ofIndexWriter.GetReader(), callDirectoryReader.Open(IndexWriter)orDirectoryReader.OpenIfChanged(IndexWriter).LUCENE-2690:
MultiTermQueryboolean rewrites per segment. AlsoMultiTermQuery.GetTermsEnum()now takes anAttributeSource.FuzzyTermsEnumis both consumer and producer of attributes:MultiTermQuery.BoostAttributeis added to theFuzzyTermsEnumandMultiTermQuery's rewrite mode consumes it. The other way roundMultiTermQuery.TopTermsBooleanQueryRewritesupplies a globalAttributeSourceto each segmentsTermsEnum. TheTermsEnumis consumer and gets the current minimum competitive boosts (MultiTermQuery.MaxNonCompetitiveBoostAttribute).LUCENE-2374: The backwards layer in
Attributewas removed. To support correct reflection ofAttributeinstances, where the reflection was done using deprecatedToString()parsing, you have to now overrideReflectWith()to customize output.ToString()is no longer implemented byAttribute, so if you have overriddenToString(), port your customization over toReflectWith().ReflectAsString()would then return whatToString()did before.LUCENE-2236, LUCENE-2912:
DefaultSimilaritycan no longer be set statically (and dangerously) for the entireAppDomain.Similaritycan now be configured on a per-field basis (viaPerFieldSimilarityWrapper)Similarityhas a lower-level API, if you want the higher-level vector-space API like in previous Lucene releases, then look atTFIDFSimilarity.LUCENE-1076:
TieredMergePolicyis now the default merge policy. It's able to merge non-contiguous segments; this may cause problems for applications that rely on Lucene's internal document ID assignment. If so, you should instead useLogByteSize/DocMergePolicyduring indexing.LUCENE-3722:
Similaritymethods and collection/term statistics now takelonginstead ofint(to enable distributed scoring of > 2B docs). For example, inTFIDFSimilarityIdf(int, int)is nowIdf(long, long).LUCENE-3559: The members
DocFreq()andMaxDoconIndexSearcherwere removed, as these are no longer used by the scoring system. If you were using these casually in your code for reasons unrelated to scoring, call them on theIndexSearcher's reader instead:IndexSearcher.IndexReader. If you were subclassingIndexSearcherand overriding these members to alter scoring, overrideIndexSearcher'sTermStatistics()andCollectionStatistics()methods instead.LUCENE-3396:
Analyzer.TokenStream()has been renamedAnalyzer.GetTokenStream().Analyzer.TokenStream()has been made sealed..ReusableTokenStream()has been removed. It is now necessary to useAnalyzer.GetTokenStreamComponents()to define an analysis process.Analyzeralso has its own way of managing the reuse ofTokenStreamComponents(either globally, or per-field). To define anotherStrategy, implementReuseStrategy.LUCENE-3464:
IndexReader.Reopen()has been renamed toDirectoryReader.OpenIfChanged()(a static method), and now returnsnull(instead of the old reader) if there are no changes to the index, to prevent the common pitfall of accidentally closing the old reader.LUCENE-3687:
Similarity.ComputeNorm()now expects aNormobject to set the computed norm value instead of returning a fixed single byte value. Custom similarities can now set integer, float and byte values if a single byte is not sufficient.LUCENE-2621: Term vectors are now accessed via flexible indexing API. If you used
IndexReader.GetTermFreqVectors()before, you should now useIndexReader.GetTermVectors(). The new method returns aFieldsinstance exposing the inverted index of the one document. FromFieldsyou can enumerate all fields, terms, positions, offsets.LUCENE-4227: If you were previously using
Instantiatedindex, you may want to useDirectPostingsFormatafter upgrading: it stores all postings in simple arrays (byte[]for terms,int[]for docs, freqs, positions, offsets). Note that this only covers postings, whereasInstantiatedcovered all other parts of the index as well.LUCENE-3309: The expert
FieldSelectorAPI has been replaced withStoredFieldVisitor. The idea is the same (you have full control over which fields should be loaded). Instead of a single accept method,StoredFieldVisitorhas aNeedsField()method: if that method returnstruethen the field will be loaded and the appropriate type-specific method will be invoked with that fields's value.LUCENE-4122: Removed the
Payloadclass and replaced withBytesRef.PayloadAttribute's name is unchanged, it just uses theBytesRefclass to refer to the payload bytes/start offset/end offset (ornullif there is no payload).