blob: 8cf47a8e6f8cde2c480475b3b14ab1b002d50e16 [file] [log] [blame]
LUCENE-2380: FieldCache.getStrings/Index --> FieldCache.getDocTerms/Index
* The field values returned when sorting by SortField.STRING are now
BytesRef. You can call value.utf8ToString() to convert back to
string, if necessary.
* In FieldCache, getStrings (returning String[]) has been replaced
with getTerms (returning a FieldCache.DocTerms instance).
DocTerms provides a getTerm method, taking a docID and a BytesRef
to fill (which must not be null), 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:
DocTerms values = FieldCache.DEFAULT.getTerms(reader, field);
...
BytesRef term = new BytesRef();
String aValue = values.getTerm(docID, term).utf8ToString();
Note however that it can be costly to convert to String, so it's
better to work directly with the BytesRef.
* Similarly, in FieldCache, getStringIndex (returning a StringIndex
instance, with direct arrays int[] order and String[] lookup) has
been replaced with getTermsIndex (returning a
FieldCache.DocTermsIndex instance). DocTermsIndex provides the
getOrd(int docID) method to lookup the int order for a document,
lookup(int ord, BytesRef reuse) to lookup the term from a given
order, and the sugar method getTerm(int docID, BytesRef reuse)
which internally calls getOrd and then lookup.
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();
String aValue = idx.lookup(ord, term).utf8ToString();
Note however that it can be costly to convert to String, so it's
better to work directly with the BytesRef.
DocTermsIndex also has a getTermsEnum() method, which returns an
iterator (TermsEnum) over the term values in the index (ie,
iterates ord = 0..numOrd()-1).
* StringComparatorLocale is now more CPU costly than it was before
(it was already very CPU costly since it does not compare using
indexed collation keys; use CollationKeyFilter for better
performance), since it converts BytesRef -> String on the fly.
Also, the field values returned when sorting by SortField.STRING
are now BytesRef.
* FieldComparator.StringOrdValComparator has been renamed to
TermOrdValComparator, and now uses BytesRef for its values.
Likewise for StringValComparator, renamed to TermValComparator.
This means when sorting by SortField.STRING or
SortField.STRING_VAL (or directly invoking these comparators) the
values returned in the FieldDoc.fields array will be BytesRef not
String. You can call the .utf8ToString() method on the BytesRef
instances, if necessary.
LUCENE-1458, LUCENE-2111: Flexible Indexing
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 the BytesRef class (which provides an offset + length "slice"
into an existing byte[]).
* Fields are separately enumerated (FieldsEnum) from the terms
within each field (TermEnum). So instead of this:
TermEnum termsEnum = ...;
while(termsEnum.next()) {
Term t = termsEnum.term();
System.out.println("field=" + t.field() + "; text=" + t.text());
}
Do this:
FieldsEnum fieldsEnum = ...;
String field;
while((field = fieldsEnum.next()) != null) {
TermsEnum termsEnum = fieldsEnum.terms();
BytesRef text;
while((text = termsEnum.next()) != null) {
System.out.println("field=" + field + "; text=" + text.utf8ToString());
}
* TermDocs is renamed to DocsEnum. 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) {
...
}
The bulk read API has also changed. Instead of this:
int[] docs = new int[256];
int[] freqs = new int[256];
while(true) {
int count = td.read(docs, freqs)
if (count == 0) {
break;
}
// use docs[i], freqs[i]
}
do this:
DocsEnum.BulkReadResult bulk = td.getBulkResult();
while(true) {
int count = td.read();
if (count == 0) {
break;
}
// use bulk.docs.ints[i] and bulk.freqs.ints[i]
}
* TermPositions is renamed to DocsAndPositionsEnum, and no longer
extends the docs only enumerator (DocsEnum).
* Deleted docs are no longer implicitly filtered from
docs/positions enums. Instead, you pass a Bits
skipDocs (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,
TermsEnum is able to seek, and then you request the
docs/positions enum from that TermsEnum.
* 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) {
...
}
SeekStatus also contains END (enumerator is done) and NOT_FOUND
(term was not found but enumerator is now positioned to the next
term).
* TermsEnum has an ord() method, 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 methods are optional; in
particular the MultiFields TermsEnum does not implement them.
How you obtain the enums has changed. The primary entry point is
the Fields class. 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 the MultiFields approach entails a performance hit on
MultiReaders, as it must merge terms/docs/positions on the fly. It's
generally better to instead get the sequential readers (use
oal.util.ReaderUtil) and then step through those readers yourself,
if you can (this is how Lucene drives searches).
If you pass a SegmentReader to MultiFields.fiels it will simply
return reader.fields(), so there is no performance hit in that
case.
Once you have a non-null Fields you can do this:
Terms terms = fields.terms("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.iterator();
The returned TermsEnum will not be null.
You can then .next() through the TermsEnum, or seek. If you want a
DocsEnum, do this:
Bits skipDocs = MultiFields.getDeletedDocs(reader);
DocsEnum docsEnum = null;
docsEnum = termsEnum.docs(skipDocs, docsEnum);
You can pass in a prior DocsEnum and it will be reused if possible.
Likewise for DocsAndPositionsEnum.
IndexReader has 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:
String field;
BytesRef text;
DocsEnum docsEnum = reader.termDocsEnum(reader.getDeletedDocs(), field, text);
Likewise for DocsAndPositionsEnum.
* LUCENE-2600: remove IndexReader.isDeleted
Instead of IndexReader.isDeleted, do this:
import org.apache.lucene.util.Bits;
import org.apache.lucene.index.MultiFields;
Bits delDocs = MultiFields.getDeletedDocs(indexReader);
if (delDocs.get(docID)) {
// document is deleted...
}
* LUCENE-2674: A new idfExplain method was added to Similarity, that
accepts an incoming docFreq. If you subclass Similarity, make sure
you also override this method on upgrade, otherwise your
customizations won't run for certain MultiTermQuerys.
* LUCENE-2413: Lucene's core and contrib analyzers, along with Solr's analyzers,
were consolidated into modules/analysis. During the refactoring some
package names have changed:
- o.a.l.analysis.KeywordAnalyzer -> o.a.l.analysis.core.KeywordAnalyzer
- o.a.l.analysis.KeywordTokenizer -> o.a.l.analysis.core.KeywordTokenizer
- o.a.l.analysis.LetterTokenizer -> o.a.l.analysis.core.LetterTokenizer
- o.a.l.analysis.LowerCaseFilter -> o.a.l.analysis.core.LowerCaseFilter
- o.a.l.analysis.LowerCaseTokenizer -> o.a.l.analysis.core.LowerCaseTokenizer
- o.a.l.analysis.SimpleAnalyzer -> o.a.l.analysis.core.SimpleAnalyzer
- o.a.l.analysis.StopAnalyzer -> o.a.l.analysis.core.StopAnalyzer
- o.a.l.analysis.StopFilter -> o.a.l.analysis.core.StopFilter
- o.a.l.analysis.WhitespaceAnalyzer -> o.a.l.analysis.core.WhitespaceAnalyzer
- o.a.l.analysis.WhitespaceTokenizer -> o.a.l.analysis.core.WhitespaceTokenizer
- o.a.l.analysis.PorterStemFilter -> o.a.l.analysis.en.PorterStemFilter
- o.a.l.analysis.ASCIIFoldingFilter -> o.a.l.analysis.miscellaneous.ASCIIFoldingFilter
- o.a.l.analysis.ISOLatin1AccentFilter -> o.a.l.analysis.miscellaneous.ISOLatin1AccentFilter
- o.a.l.analysis.KeywordMarkerFilter -> o.a.l.analysis.miscellaneous.KeywordMarkerFilter
- o.a.l.analysis.LengthFilter -> o.a.l.analysis.miscellaneous.LengthFilter
- o.a.l.analysis.PerFieldAnalyzerWrapper -> o.a.l.analysis.miscellaneous.PerFieldAnalyzerWrapper
- o.a.l.analysis.TeeSinkTokenFilter -> o.a.l.analysis.sinks.TeeSinkTokenFilter
- o.a.l.analysis.CharFilter -> o.a.l.analysis.charfilter.CharFilter
- o.a.l.analysis.BaseCharFilter -> o.a.l.analysis.charfilter.BaseCharFilter
- o.a.l.analysis.MappingCharFilter -> o.a.l.analysis.charfilter.MappingCharFilter
- o.a.l.analysis.NormalizeCharMap -> o.a.l.analysis.charfilter.NormalizeCharMap
- o.a.l.analysis.CharArraySet -> o.a.l.analysis.util.CharArraySet
- o.a.l.analysis.CharArrayMap -> o.a.l.analysis.util.CharArrayMap
- o.a.l.analysis.ReusableAnalyzerBase -> o.a.l.analysis.util.ReusableAnalyzerBase
- o.a.l.analysis.StopwordAnalyzerBase -> o.a.l.analysis.util.StopwordAnalyzerBase
- o.a.l.analysis.WordListLoader -> o.a.l.analysis.util.WordListLoader
- o.a.l.analysis.CharTokenizer -> o.a.l.analysis.util.CharTokenizer
- o.a.l.util.CharacterUtils -> o.a.l.analysis.util.CharacterUtils
* LUCENE-2514: The option to use a Collator's order (instead of binary order) for
sorting and range queries has been moved to contrib/queries.
The Collated TermRangeQuery/Filter has been moved to SlowCollatedTermRangeQuery/Filter,
and the collated sorting has been moved to SlowCollatedStringComparator.
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 a suitable collating analyzer: CollationKeyAnalyzer
or ICUCollationKeyAnalyzer, and set qp.setAnalyzeRangeTerms(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-2691: The near-real-time API has moved from IndexWriter to
IndexReader. Instead of IndexWriter.getReader(), call
IndexReader.open(IndexWriter) or IndexReader.reopen(IndexWriter).
* LUCENE-2690: MultiTermQuery boolean rewrites per segment.
Also MultiTermQuery.getTermsEnum() now takes an AttributeSource. FuzzyTermsEnum
is both consumer and producer of attributes: MTQ.BoostAttribute is
added to the FuzzyTermsEnum and MTQ's rewrite mode consumes it.
The other way round MTQ.TopTermsBooleanQueryRewrite supplys a
global AttributeSource to each segments TermsEnum. The TermsEnum is consumer
and gets the current minimum competitive boosts (MTQ.MaxNonCompetitiveBoostAttribute).
* LUCENE-2374: The backwards layer in AttributeImpl was removed. To support correct
reflection of AttributeImpl instances, where the reflection was done using deprecated
toString() parsing, you have to now override reflectWith() to customize output.
toString() is no longer implemented by AttributeImpl, so if you have overridden
toString(), port your customization over to reflectWith(). reflectAsString() would
then return what toString() did before.
* LUCENE-2236, LUCENE-2912: DefaultSimilarity can no longer be set statically
(and dangerously) for the entire JVM.
Instead, IndexWriterConfig and IndexSearcher now take a SimilarityProvider.
Similarity can now be configured on a per-field basis.
Similarity retains only the field-specific relevance methods such as tf() and idf().
Previously some (but not all) of these methods, such as computeNorm and scorePayload took
field as a parameter, this is removed due to the fact the entire Similarity (all methods)
can now be configured per-field.
Methods that apply to the entire query such as coord() and queryNorm() exist in SimilarityProvider.
* LUCENE-1076: TieredMergePolicy is 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
assigment. If so, you should instead use LogByteSize/DocMergePolicy
during indexing.
* LUCENE-2883: Lucene's o.a.l.search.function ValueSource based functionality, was consolidated
into module/queries along with Solr's similar functionality. The following classes were moved:
- o.a.l.search.function.CustomScoreQuery -> o.a.l.queries.CustomScoreQuery
- o.a.l.search.function.CustomScoreProvider -> o.a.l.queries.CustomScoreProvider
- o.a.l.search.function.NumericIndexDocValueSource -> o.a.l.queries.function.valuesource.NumericIndexDocValueSource
The following lists the replacement classes for those removed:
- o.a.l.search.function.ByteFieldSource -> o.a.l.queries.function.valuesource.ByteFieldSource
- o.a.l.search.function.DocValues -> o.a.l.queries.function.DocValues
- o.a.l.search.function.FieldCacheSource -> o.a.l.queries.function.valuesource.FieldCacheSource
- o.a.l.search.function.FieldScoreQuery ->o.a.l.queries.function.FunctionQuery
- o.a.l.search.function.FloatFieldSource -> o.a.l.queries.function.valuesource.FloatFieldSource
- o.a.l.search.function.IntFieldSource -> o.a.l.queries.function.valuesource.IntFieldSource
- o.a.l.search.function.OrdFieldSource -> o.a.l.queries.function.valuesource.OrdFieldSource
- o.a.l.search.function.ReverseOrdFieldSource -> o.a.l.queries.function.valuesource.ReverseOrdFieldSource
- o.a.l.search.function.ShortFieldSource -> o.a.l.queries.function.valuesource.ShortFieldSource
- o.a.l.search.function.ValueSource -> o.a.l.queries.function.ValueSource
- o.a.l.search.function.ValueSourceQuery -> o.a.l.queries.function.FunctionQuery
* 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: Lucene's core o.a.l.queryParser QueryParsers have been consolidated into module/queryparser,
where other QueryParsers from the codebase will also be placed. The following classes were moved:
- o.a.l.queryParser.CharStream -> o.a.l.queryparser.classic.CharStream
- o.a.l.queryParser.FastCharStream -> o.a.l.queryparser.classic.FastCharStream
- o.a.l.queryParser.MultiFieldQueryParser -> o.a.l.queryparser.classic.MultiFieldQueryParser
- o.a.l.queryParser.ParseException -> o.a.l.queryparser.classic.ParseException
- o.a.l.queryParser.QueryParser -> o.a.l.queryparser.classic.QueryParser
- o.a.l.queryParser.QueryParserBase -> o.a.l.queryparser.classic.QueryParserBase
- o.a.l.queryParser.QueryParserConstants -> o.a.l.queryparser.classic.QueryParserConstants
- o.a.l.queryParser.QueryParserTokenManager -> o.a.l.queryparser.classic.QueryParserTokenManager
- o.a.l.queryParser.QueryParserToken -> o.a.l.queryparser.classic.Token
- o.a.l.queryParser.QueryParserTokenMgrError -> o.a.l.queryparser.classic.TokenMgrError
* LUCENE-2308: 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 IndexableFieldType 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 a String value 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 exposes TYPE_STORED as well.
* BinaryField: a byte[] value that's only stored.
* TextField: indexes and tokenizes a String, Reader or TokenStream
value, without term vectors. This field does not store its value,
but exposes TYPE_STORED as well.
If your usage fits one of those common cases you can simply
instantiate the above class. To use the TYPE_STORED variant, do this
instead:
Field f = new Field("field", StringField.TYPE_STORED, "value");
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);
bodyType.setStoreTermVectors(true);
You can of course also create your own FieldType from scratch:
FieldType t = new FieldType();
t.setIndexed(true);
t.setStored(true);
t.setOmitNorms(true);
t.setIndexOptions(IndexOptions.DOCS_AND_FREQS);
FieldType has a freeze() method to prevent further changes.
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", StringField.TYPE_STORED, "value")
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(StringField.TYPE_STORED);
ft.setOmitNorms(false);
new Field("field", ft, "value")
If you did this before (value can be String or Reader):
new Field("field", value, Field.Store.NO, Field.Indexed.ANALYZED)
you can now do this:
new TextField("field", value)
If instead the value was stored:
new Field("field", value, Field.Store.YES, Field.Indexed.ANALYZED)
you can now do this:
new Field("field", TextField.TYPE_STORED, value)
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);
ft.setOmitNorms(true);
new Field("field", ft, value)
If you did this before (bytes is a byte[]):
new Field("field", bytes)
you can now do this:
new BinaryField("field", bytes)