Lucene upgrade
This page contains breaking changes related to the upgrade of the Lucene library from version 3.3 to 7.3.
Changes
Jira code and jira-lucene-dmz.jar
Several methods have been removed from the Jira code, because they're no longer needed. For some, we've provided alternatives you can use.
com.atlassian.jira.util.BuildUtilsInfo#getLuceneVersion
Changes:
Class removed.
com.atlassian.jira.issue.index.indexers.impl.VersionCustomFieldIndexer
Method being changed:
public void addDocumentFields(final Document doc, final Issue issue, final Field.Index indexType)
Changes:
To index and store a field, use this method:
addDocumentFieldsSearchable(final Document doc, final Issue issue)
To store a field without indexing it, use this method:
addDocumentFieldsNotSearchable(final Document doc, final Issue issue)
com/atlassian/jira/config/properties/APKeys$JiraIndexConfiguration
Changes:
The getMaxFieldLength
has been removed.
com/atlassian/jira/config/properties/APKeys$JiraIndexConfiguration$MergePolicy
Changes:
The EXPUNGE_DELETES_PCT_ALLOWED
has been removed.
com.atlassian.jira.web.component.IssuePage
com.atlassian.jira.web.component.IssuePager
Changes:
Renamed → com.atlassian.jira.web.component.ResultPage
Renamed → com.atlassian.jira.web.component.Pager
com.atlassian.jira.issue.search.SearchResults
Changes:
- used to hold List<Issue>
Now →
holds List<T>
SearchService uses List<Issue>
,SearchProvider uses List<DocumentWithId>
- method getIssues
→ Renamed to getResults
- new method transform
for transforming results of one type to another
- class used to have 3 constructors → Old constructor logic moved to com.atlassian.jira.issue.search.IssueSearchResultsFactory
and com.atlassian.jira.issue.search.DocumentSearchResultsFactory
com.atlassian.jira.issue.search.SearchProvider
Changes:
searchCount
→ Renamed →getHitCount
search
:parameters packed into the
com.atlassian.jira.issue.search.SearchQuery
objectnew parameter
fieldsToLoad
to restrict which document fields are loaded, ok to pass empty set to load only document
New return type
com.atlassian.jira.issue.search.DocumentWithId
that holds loaded Lucene document and its internal Lucene id. This id is only valid in the context of currentIndexReader
- don't cache it.searchAndSort
withCollector
removed (usual search withCollector
remains)Collector collector = new MyCollector(); searchProvider.searchAndSort(query, user, collector, pager); return collector.getResults();
com.atlassian.jira.index.ManagedIndexSearcher
In the org.apache.lucene.search.IndexSearcher
it was not clear who manages the searcher's lifecycle.
Changes:
Now we have 2 new classes:
com.atlassian.jira.index.ManagedIndexSearcher
that does not need to be closed manuallycom.atlassian.jira.index.UnmanagedIndexSearcher
which has to be closed by its user
AbstractOneDimensionalHitCollector
DocumentHitCollector
Changes:
changed to public void doSetNextReader(LeafReaderContext context)
FieldableDocumentHitCollector
Changes:
Class renamed to FieldDocumentHitCollector
MappedSortComparator
public FieldComparator newComparator(String fieldname, int numHits, int sortPos, boolean reversed)
throws IOException
Changes:
public FieldComparator newComparator(String fieldname, int numHits, int sortPos, boolean reversed)
OneDimensionalTermHitCollector
public OneDimensionalTermHitCollector (final String fieldId, final FieldVisibilityManager fieldVisibilityManager, final ReaderCache readerCache, final FieldManager fieldManager, final ProjectManager projectManager)
Changes:
public OneDimensionalTermHitCollector(final String fieldId, final FieldVisibilityManager fieldVisibilityManager, final ReaderCache readerCache, final FieldManager fieldManager
ReaderCache
Collection<String>[] get(LeafReader reader, String key, Supplier<Collection<String>[]> supplier);
JiraDocValues getDocValues(LeafReader indexReader, String field);
Changes:
{@link ReaderCache}
is using Lucene {@link org.apache.lucene.index.DocValues}
JiraDocValues getDocValues(IndexReader indexReader, String field);
CustomFieldStattable
StatisticsMapper getStatisticsMapper(CustomField customField);
Changes:
Contract change; starting from Jira 8.0 onwards a "stattable" field must have a doc value of type:
{@link org.apache.lucene.index.SortedDocValues},
{@link org.apache.lucene.index.SortedSetDocValues}
, or {@link org.apache.lucene.index.BinaryDocValues}
com.atlassian.jira.jql.util.JqlDateSupport
Changes:
Removed getIndexedValue →
Now dates are stored directly as longs in the index.
com.atlassian.jira.jql.util.JqlLocalDateSupport
Changes:
Removed getIndexedValue
→ Now local dates are stored directly as longs in the index.
com.atlassian.jira.util.LuceneUtils
Various methods for converting dates and local dates to and from the old String-based index formats.
Changes:
This class was removed. Now dates & local dates are added to the index as longs.
com.atlassian.jira.issue.customfields.NaturallyOrderedCustomFieldsSearcher
Changes:
Expanded SPI by one method: public SortField.Type getSortFieldType();
com.atlassian.jira.index.NumberTools
com.atlassian.jira.util.LuceneNumericUtils
moved → com.atlassian.jira.lucenelegacy.NumberTools
moved → com.atlassian.jira.lucenelegacy.NumericUtils
com.atlassian.jira.issue.search.QueryPermissions
Removed → see com.atlassian.jira.issue.search.SearchQuery
com.atlassian.jira.issue.search.SearchQuery
Changes:
QueryPermissions
field removed- Set
ApplicationUser user
andboolean overrideSecurity
directly user
is used for permissions and to createcom.atlassian.jira.jql.query.QueryCreationContext.
It is needed even whenoverrideSecurity = true
.
- Set
create
methods removed:
create(Query,QueryPermissions, org.apache.lucene.search.Query)
create(Query,QueryPermissions)
createNoPermissions(Query)
Changes:
To further configureSearchQuery,
use the following:SearchQuery.create(query, user)
overrideSecurity(true)
luceneQuery(andQuery);
Lucene API exposed by Jira
Creating BooleanQuery
Using constructors to create boolean queries is no longer supported. Instead, you'll need to use the query builder.
Creating Documents
To specify fields in the document, you'll now need to use the subclasses of the Field class (i.e. StringField
, TextField
, StoredField
).
Creating Filters
The org.apache.lucene.search.Filter
class has changed to the regular org.apache.lucene.search.Query
with BooleanClause.Occur.FILTER
occurrence.
Configuration
Several configuration items have been removed, and substituted with the new ones.
Obsolete configuration | New configuration |
---|---|
| mergePolicy.setForceMergeDeletesPctAllowed
|
mergePolicy.setUseCompoundFile
| indexWriterConfig.setUseCompoundFile
|
- | mergePolicy.setReclaimDeletesWeight
|
- | mergePolicy.setMaxCFSSegmentSizeMB
|
JQL changes
Fuzzy Search
Old Lucene | New Lucene |
---|---|
|
Where 0 is an exact match and 2 allows 2 changes. |
Index is seen as a swap file
Doc values are stored in virtual address space, so it might look like Java process takes up lots of memory (3x index file), but this is not real RAM, just memory-mapped files, which are swapped in and out as needed.
Re-indexing
When moving from any version of Jira older than EAP 04 to a version higher than EAP 04 or the actual EAP 04, a full foreground reindex must be performed. In EAP 04, we changed how we're storing Dates in the Lucene index. A background re-index won't do the trick, as it leaves Lucene in a bad state (with a mix of types under the same field name).