DirectoryReader (Lucene 10.5.0 core API)
Description: declaration: package: org.apache.lucene.index, class: DirectoryReader

Package org.apache.lucene.index

# Class DirectoryReader

java.lang.Object
org.apache.lucene.index.IndexReader
org.apache.lucene.index.CompositeReader
org.apache.lucene.index.BaseCompositeReader<LeafReader>
org.apache.lucene.index.DirectoryReader

All Implemented Interfaces:
  `Closeable`, `AutoCloseable`

Direct Known Subclasses:
  `FilterDirectoryReader`, `StandardDirectoryReader`

public abstract class DirectoryReader extends BaseCompositeReader<LeafReader>
DirectoryReader is an implementation of `CompositeReader` that can read indexes in a `Directory`.

DirectoryReader instances are usually constructed with a call to one of the static `open()` methods, e.g. `open(Directory)`.

For efficiency, in this API documents are often referred to via document numbers, non-negative integers which each name a unique document in the index. These document numbers are ephemeral -- they may change as documents are added to and deleted from an index. Clients should thus not rely on a given document having the same number between sessions.

NOTE: `IndexReader` instances are completely thread safe, meaning multiple threads can call any of its methods, concurrently. If your application requires external synchronization, you should not synchronize on the `IndexReader` instance; use your own (non-Lucene) objects instead.

- ## Nested Class Summary

  ## Nested classes/interfaces inherited from class org.apache.lucene.index.IndexReader

  `IndexReader.CacheHelper, IndexReader.CacheKey, IndexReader.ClosedListener`

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `protected final Directory`
  `directory`
  The index directory.

  ### Fields inherited from class org.apache.lucene.index.BaseCompositeReader

  `subReadersSorter`

- ## Constructor Summary

  Constructors
  Modifier
  Constructor
  Description
  `protected`
  `DirectoryReader(Directory directory, LeafReader[] segmentReaders, Comparator<LeafReader> leafSorter)`
  Expert: Constructs a `DirectoryReader` on the given subReaders.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `final Directory`
  `directory()`
  Returns the directory this index resides in.
  `protected abstract DirectoryReader`
  `doOpenIfChanged()`
  Implement this method to support `openIfChanged(DirectoryReader)`.
  `protected abstract DirectoryReader`
  `doOpenIfChanged(ExecutorService executorService)`
  Implement this method to support `openIfChanged(DirectoryReader)`.
  `protected abstract DirectoryReader`
  `doOpenIfChanged(IndexCommit commit)`
  Implement this method to support `openIfChanged(DirectoryReader,IndexCommit)`.
  `protected abstract DirectoryReader`
  `doOpenIfChanged(IndexCommit commit, ExecutorService executorService)`
  Implement this method to support `openIfChanged(DirectoryReader,IndexCommit)`.
  `protected abstract DirectoryReader`
  `doOpenIfChanged(IndexWriter writer, boolean applyAllDeletes)`
  Implement this method to support `openIfChanged(DirectoryReader,IndexWriter,boolean)`.
  `protected abstract DirectoryReader`
  `doOpenIfChanged(IndexWriter writer, boolean applyAllDeletes, ExecutorService executorService)`
  Implement this method to support `openIfChanged(DirectoryReader,IndexWriter,boolean)`.
  `abstract IndexCommit`
  `getIndexCommit()`
  Expert: return the IndexCommit that this reader has opened.
  `abstract long`
  `getVersion()`
  Version number when this IndexReader was opened.
  `static boolean`
  `indexExists(Directory directory)`
  Returns `true` if an index likely exists at the specified directory.
  `abstract boolean`
  `isCurrent()`
  Check whether any new changes have occurred to the index since this reader was opened.
  `static List<IndexCommit>`
  `listCommits(Directory dir)`
  Returns all commit points that exist in the Directory.
  `static DirectoryReader`
  `open(IndexCommit commit)`
  Expert: returns an IndexReader reading the index in the given `IndexCommit`.
  `static DirectoryReader`
  `open(IndexCommit commit, int minSupportedMajorVersion, Comparator<LeafReader> leafSorter)`
  Expert: returns an IndexReader reading the index on the given `IndexCommit`.
  `static DirectoryReader`
  `open(IndexCommit commit, int minSupportedMajorVersion, Comparator<LeafReader> leafSorter, ExecutorService executorService)`
  Expert: returns an IndexReader reading the index on the given `IndexCommit`.
  `static DirectoryReader`
  `open(IndexCommit commit, ExecutorService executorService)`
  Expert: returns an IndexReader reading the index in the given `IndexCommit`.
  `static DirectoryReader`
  `open(IndexWriter writer)`
  Open a near real time IndexReader from the `IndexWriter`.
  `static DirectoryReader`
  `open(IndexWriter writer, boolean applyAllDeletes, boolean writeAllDeletes)`
  Expert: open a near real time IndexReader from the `IndexWriter`, controlling whether past deletions should be applied.
  `static DirectoryReader`
  `open(Directory directory)`
  Returns a IndexReader reading the index in the given Directory
  `static DirectoryReader`
  `open(Directory directory, Comparator<LeafReader> leafSorter)`
  Returns a IndexReader for the index in the given Directory
  `static DirectoryReader`
  `open(Directory directory, Comparator<LeafReader> leafSorter, ExecutorService executorService)`
  Returns a IndexReader for the index in the given Directory
  `static DirectoryReader`
  `open(Directory directory, ExecutorService executorService)`
  Returns a IndexReader reading the index in the given Directory
  `static DirectoryReader`
  `openIfChanged(DirectoryReader oldReader)`
  If the index has changed since the provided reader was opened, open and return a new reader; else, return null.
  `static DirectoryReader`
  `openIfChanged(DirectoryReader oldReader, ExecutorService executorService)`
  If the index has changed since the provided reader was opened, open and return a new reader; else, return null.
  `static DirectoryReader`
  `openIfChanged(DirectoryReader oldReader, IndexCommit commit)`
  If the IndexCommit differs from what the provided reader is searching, open and return a new reader; else, return null.
  `static DirectoryReader`
  `openIfChanged(DirectoryReader oldReader, IndexCommit commit, ExecutorService executorService)`
  If the IndexCommit differs from what the provided reader is searching, open and return a new reader; else, return null.
  `static DirectoryReader`
  `openIfChanged(DirectoryReader oldReader, IndexWriter writer)`
  Expert: If there changes (committed or not) in the `IndexWriter` versus what the provided reader is searching, then open and return a new IndexReader searching both committed and uncommitted changes from the writer; else, return null (though, the current implementation never returns null).
  `static DirectoryReader`
  `openIfChanged(DirectoryReader oldReader, IndexWriter writer, boolean applyAllDeletes)`
  Expert: Opens a new reader, if there are any changes, controlling whether past deletions should be applied.
  `static DirectoryReader`
  `openIfChanged(DirectoryReader oldReader, IndexWriter writer, boolean applyAllDeletes, ExecutorService executorService)`
  Expert: Opens a new reader, if there are any changes, controlling whether past deletions should be applied.
  `static DirectoryReader`
  `openIfChanged(DirectoryReader oldReader, IndexWriter writer, ExecutorService executorService)`
  Expert: If there changes (committed or not) in the `IndexWriter` versus what the provided reader is searching, then open and return a new IndexReader searching both committed and uncommitted changes from the writer; else, return null (though, the current implementation never returns null).

  ### Methods inherited from class org.apache.lucene.index.BaseCompositeReader

  `docFreq, getDocCount, getSequentialSubReaders, getSumDocFreq, getSumTotalTermFreq, maxDoc, numDocs, readerBase, readerIndex, storedFields, termVectors, totalTermFreq`

  ### Methods inherited from class org.apache.lucene.index.CompositeReader

  `getContext, toString`

  ### Methods inherited from class org.apache.lucene.index.IndexReader

  `close, decRef, doClose, ensureOpen, equals, getReaderCacheHelper, getRefCount, hasDeletions, hashCode, incRef, leaves, notifyReaderClosedListeners, numDeletedDocs, registerParentReader, tryIncRef`

  ### Methods inherited from class java.lang.Object

  `clone, finalize, getClass, notify, notifyAll, wait, wait, wait`

- ## Field Details

  - ### directory

    protected final Directory directory
    The index directory.

- ## Constructor Details

  - ### DirectoryReader

    protected DirectoryReader(Directory directory, LeafReader[] segmentReaders, Comparator<LeafReader> leafSorter) throws IOException
    Expert: Constructs a `DirectoryReader` on the given subReaders.
    Parameters:
      `segmentReaders` - the wrapped atomic index segment readers. This array is returned by `BaseCompositeReader.getSequentialSubReaders()` and used to resolve the correct subreader for docID-based methods. Please note: This array is not cloned and not protected for modification outside of this reader. Subclasses of `DirectoryReader` should take care to not allow modification of this internal array, e.g. `doOpenIfChanged()`.
      `leafSorter` - – a comparator for sorting leaf readers. If not `null`, this comparator is used for sorting leaf readers.
    Throws:
      `IOException`

- ## Method Details

  - ### open

    public static DirectoryReader open(Directory directory) throws IOException
    Returns a IndexReader reading the index in the given Directory
    Parameters:
      `directory` - the index directory
    Throws:
      `IOException` - if there is a low-level IO error

  - ### open

    public static DirectoryReader open(Directory directory, ExecutorService executorService) throws IOException
    Returns a IndexReader reading the index in the given Directory
    Parameters:
      `directory` - the index directory
      `executorService` - used to open segment readers in parallel
    Throws:
      `IOException` - if there is a low-level IO error

  - ### open

    public static DirectoryReader open(Directory directory, Comparator<LeafReader> leafSorter) throws IOException
    Returns a IndexReader for the index in the given Directory
    Parameters:
      `directory` - the index directory
      `leafSorter` - a comparator for sorting leaf readers. Providing leafSorter is useful for indices on which it is expected to run many queries with particular sort criteria (e.g. for time-based indices this is usually a descending sort on timestamp). In this case `leafSorter` should sort leaves according to this sort criteria. Providing leafSorter allows to speed up this particular type of sort queries by early terminating while iterating through segments and segments' documents.
    Throws:
      `IOException` - if there is a low-level IO error

  - ### open

    public static DirectoryReader open(Directory directory, Comparator<LeafReader> leafSorter, ExecutorService executorService) throws IOException
    Returns a IndexReader for the index in the given Directory
    Parameters:
      `directory` - the index directory
      `leafSorter` - a comparator for sorting leaf readers. Providing leafSorter is useful for indices on which it is expected to run many queries with particular sort criteria (e.g. for time-based indices this is usually a descending sort on timestamp). In this case `leafSorter` should sort leaves according to this sort criteria. Providing leafSorter allows to speed up this particular type of sort queries by early terminating while iterating through segments and segments' documents.
      `executorService` - used to open segment readers in parallel
    Throws:
      `IOException` - if there is a low-level IO error

  - ### open

    public static DirectoryReader open(IndexWriter writer) throws IOException
    Open a near real time IndexReader from the `IndexWriter`.
    Parameters:
      `writer` - The IndexWriter to open from
    Returns:
      The new IndexReader
    Throws:
      `CorruptIndexException` - if the index is corrupt
      `IOException` - if there is a low-level IO error
    See Also:
      - `openIfChanged(DirectoryReader,IndexWriter,boolean)`
    WARNING: This API is experimental and might change in incompatible ways in the next release.

  - ### open

    public static DirectoryReader open(IndexWriter writer, boolean applyAllDeletes, boolean writeAllDeletes) throws IOException
    Expert: open a near real time IndexReader from the `IndexWriter`, controlling whether past deletions should be applied.
    Parameters:
      `writer` - The IndexWriter to open from
      `applyAllDeletes` - If true, all buffered deletes will be applied (made visible) in the returned reader. If false, the deletes are not applied but remain buffered (in IndexWriter) so that they will be applied in the future. Applying deletes can be costly, so if your app can tolerate deleted documents being returned you might gain some performance by passing false.
      `writeAllDeletes` - If true, new deletes will be written down to index files instead of carried over from writer to reader directly in heap
    Throws:
      `IOException`
    See Also:
      - `open(IndexWriter)`
    WARNING: This API is experimental and might change in incompatible ways in the next release.

  - ### open

    public static DirectoryReader open(IndexCommit commit) throws IOException
    Expert: returns an IndexReader reading the index in the given `IndexCommit`.
    Parameters:
      `commit` - the commit point to open
    Throws:
      `IOException` - if there is a low-level IO error

  - ### open

    public static DirectoryReader open(IndexCommit commit, ExecutorService executorService) throws IOException
    Expert: returns an IndexReader reading the index in the given `IndexCommit`.
    Parameters:
      `commit` - the commit point to open
      `executorService` - used to open segment readers in parallel
    Throws:
      `IOException` - if there is a low-level IO error

  - ### open

    public static DirectoryReader open(IndexCommit commit, int minSupportedMajorVersion, Comparator<LeafReader> leafSorter) throws IOException
    Expert: returns an IndexReader reading the index on the given `IndexCommit`. This method allows to open indices that were created wih a Lucene version older than N-1 provided that all codecs for this index are available in the classpath and the segment file format used was created with Lucene 7 or newer. Users of this API must be aware that Lucene doesn't guarantee semantic compatibility for indices created with versions older than N-1. All backwards compatibility aside from the file format is optional and applied on a best effort basis.
    Parameters:
      `commit` - the commit point to open
      `minSupportedMajorVersion` - the minimum supported major index version
      `leafSorter` - a comparator for sorting leaf readers. Providing leafSorter is useful for indices on which it is expected to run many queries with particular sort criteria (e.g. for time-based indices, this is usually a descending sort on timestamp). In this case `leafSorter` should sort leaves according to this sort criteria. Providing leafSorter allows to speed up this particular type of sort queries by early terminating while iterating through segments and segments' documents
    Throws:
      `IOException` - if there is a low-level IO error

  - ### open

    public static DirectoryReader open(IndexCommit commit, int minSupportedMajorVersion, Comparator<LeafReader> leafSorter, ExecutorService executorService) throws IOException
    Expert: returns an IndexReader reading the index on the given `IndexCommit`. This method allows to open indices that were created with a Lucene version older than N-1 provided that all codecs for this index are available in the classpath and the segment file format used was created with Lucene 7 or newer. Users of this API must be aware that Lucene doesn't guarantee semantic compatibility for indices created with versions older than N-1. All backwards compatibility aside from the file format is optional and applied on a best effort basis.
    Parameters:
      `commit` - the commit point to open
      `minSupportedMajorVersion` - the minimum supported major index version
      `leafSorter` - a comparator for sorting leaf readers. Providing leafSorter is useful for indices on which it is expected to run many queries with particular sort criteria (e.g. for time-based indices, this is usually a descending sort on timestamp). In this case `leafSorter` should sort leaves according to this sort criteria. Providing leafSorter allows to speed up this particular type of sort queries by early terminating while iterating through segments and segments' documents
      `executorService` - used to open segment readers in parallel
    Throws:
      `IOException` - if there is a low-level IO error

  - ### openIfChanged

    public static DirectoryReader openIfChanged(DirectoryReader oldReader) throws IOException
    If the index has changed since the provided reader was opened, open and return a new reader; else, return null. The new reader, if not null, will be the same type of reader as the previous one, ie an NRT reader will open a new NRT reader, a MultiReader will open a new MultiReader, etc.

    This method is typically far less costly than opening a fully new `DirectoryReader` as it shares resources (for example sub-readers) with the provided `DirectoryReader`, when possible.

    The provided reader is not closed (you are responsible for doing so); if a new reader is returned you also must eventually close it. Be sure to never close a reader while other threads are still using it; see `SearcherManager` to simplify managing this.

    Returns:
      null if there are no changes; else, a new DirectoryReader instance which you must eventually close
    Throws:
      `CorruptIndexException` - if the index is corrupt
      `IOException` - if there is a low-level IO error

  - ### openIfChanged

    public static DirectoryReader openIfChanged(DirectoryReader oldReader, ExecutorService executorService) throws IOException
    If the index has changed since the provided reader was opened, open and return a new reader; else, return null. The new reader, if not null, will be the same type of reader as the previous one, ie an NRT reader will open a new NRT reader etc.

    This method is typically far less costly than opening a fully new `DirectoryReader` as it shares resources (for example sub-readers) with the provided `DirectoryReader`, when possible.

    The provided reader is not closed (you are responsible for doing so); if a new reader is returned you also must eventually close it. Be sure to never close a reader while other threads are still using it; see `SearcherManager` to simplify managing this.

    Returns:
      null if there are no changes; else, a new DirectoryReader instance which you must eventually close
    Throws:
      `CorruptIndexException` - if the index is corrupt
      `IOException` - if there is a low-level IO error

  - ### openIfChanged

    public static DirectoryReader openIfChanged(DirectoryReader oldReader, IndexCommit commit) throws IOException
    If the IndexCommit differs from what the provided reader is searching, open and return a new reader; else, return null.
    Throws:
      `IOException`
    See Also:
      - `openIfChanged(DirectoryReader)`

  - ### openIfChanged

    public static DirectoryReader openIfChanged(DirectoryReader oldReader, IndexCommit commit, ExecutorService executorService) throws IOException
    If the IndexCommit differs from what the provided reader is searching, open and return a new reader; else, return null. Executor service used to open segment readers in parallel.
    Throws:
      `IOException`
    See Also:
      - `openIfChanged(DirectoryReader)`

  - ### openIfChanged

    public static DirectoryReader openIfChanged(DirectoryReader oldReader, IndexWriter writer) throws IOException
    Expert: If there changes (committed or not) in the `IndexWriter` versus what the provided reader is searching, then open and return a new IndexReader searching both committed and uncommitted changes from the writer; else, return null (though, the current implementation never returns null).

    This provides "near real-time" searching, in that changes made during an `IndexWriter` session can be quickly made available for searching without closing the writer nor calling `IndexWriter.commit()`.

    It's near real-time because there is no hard guarantee on how quickly you can get a new reader after making changes with IndexWriter. You'll have to experiment in your situation to determine if it's fast enough. As this is a new and experimental feature, please report back on your findings so we can learn, improve and iterate.

    The very first time this method is called, this writer instance will make every effort to pool the readers that it opens for doing merges, applying deletes, etc. This means additional resources (RAM, file descriptors, CPU time) will be consumed.

    For lower latency on reopening a reader, you should call `IndexWriterConfig.setMergedSegmentWarmer(org.apache.lucene.index.IndexWriter.IndexReaderWarmer)` to pre-warm a newly merged segment before it's committed to the index. This is important for minimizing index-to-search delay after a large merge.

    If an addIndexes* call is running in another thread, then this reader will only search those segments from the foreign index that have been successfully copied over, so far.

    NOTE: Once the writer is closed, any outstanding readers may continue to be used. However, if you attempt to reopen any of those readers, you'll hit an `AlreadyClosedException`.

    Parameters:
      `writer` - The IndexWriter to open from
    Returns:
      DirectoryReader that covers entire index plus all changes made so far by this IndexWriter instance, or null if there are no new changes
    Throws:
      `IOException` - if there is a low-level IO error
    WARNING: This API is experimental and might change in incompatible ways in the next release.

  - ### openIfChanged

    public static DirectoryReader openIfChanged(DirectoryReader oldReader, IndexWriter writer, ExecutorService executorService) throws IOException
    Expert: If there changes (committed or not) in the `IndexWriter` versus what the provided reader is searching, then open and return a new IndexReader searching both committed and uncommitted changes from the writer; else, return null (though, the current implementation never returns null).

    This provides "near real-time" searching, in that changes made during an `IndexWriter` session can be quickly made available for searching without closing the writer or calling `IndexWriter.commit()`.

    It's near real-time because there is no hard guarantee on how quickly you can get a new reader after making changes with IndexWriter. You'll have to experiment in your situation to determine if it's fast enough. As this is a new and experimental feature, please report back on your findings so we can learn, improve and iterate.

    The very first time this method is called, this writer instance will make every effort to pool the readers that it opens for doing merges, applying deletes, etc. This means additional resources (RAM, file descriptors, CPU time) will be consumed.

    For lower latency on reopening a reader, you should call `IndexWriterConfig.setMergedSegmentWarmer(org.apache.lucene.index.IndexWriter.IndexReaderWarmer)` to pre-warm a newly merged segment before it's committed to the index. This is important for minimizing index-to-search delay after a large merge.

    If an addIndexes* call is running in another thread, then this reader will only search those segments from the foreign index that have been successfully copied over, so far.

    NOTE: Once the writer is closed, any outstanding readers may continue to be used. However, if you attempt to reopen any of those readers, you'll hit an `AlreadyClosedException`.

    Parameters:
      `writer` - The IndexWriter to open from
      `executorService` - used to open segment readers in parallel
    Returns:
      DirectoryReader that covers entire index plus all changes made so far by this IndexWriter instance, or null if there are no new changes
    Throws:
      `IOException` - if there is a low-level IO error
    WARNING: This API is experimental and might change in incompatible ways in the next release.

  - ### openIfChanged

    public static DirectoryReader openIfChanged(DirectoryReader oldReader, IndexWriter writer, boolean applyAllDeletes) throws IOException
    Expert: Opens a new reader, if there are any changes, controlling whether past deletions should be applied.
    Parameters:
      `writer` - The IndexWriter to open from
      `applyAllDeletes` - If true, all buffered deletes will be applied (made visible) in the returned reader. If false, the deletes are not applied but remain buffered (in IndexWriter) so that they will be applied in the future. Applying deletes can be costly, so if your app can tolerate deleted documents being returned you might gain some performance by passing false.
    Throws:
      `IOException` - if there is a low-level IO error
    See Also:
      - `openIfChanged(DirectoryReader,IndexWriter)`
    WARNING: This API is experimental and might change in incompatible ways in the next release.

  - ### openIfChanged

    public static DirectoryReader openIfChanged(DirectoryReader oldReader, IndexWriter writer, boolean applyAllDeletes, ExecutorService executorService) throws IOException
    Expert: Opens a new reader, if there are any changes, controlling whether past deletions should be applied.
    Parameters:
      `writer` - The IndexWriter to open from
      `applyAllDeletes` - If true, all buffered deletes will be applied (made visible) in the returned reader. If false, the deletes are not applied but remain buffered (in IndexWriter) so that they will be applied in the future. Applying deletes can be costly, so if your app can tolerate deleted documents being returned you might gain some performance by passing false.
      `executorService` - used to open segment readers in parallel
    Throws:
      `IOException` - if there is a low-level IO error
    See Also:
      - `openIfChanged(DirectoryReader,IndexWriter)`
    WARNING: This API is experimental and might change in incompatible ways in the next release.

  - ### listCommits

    public static List<IndexCommit> listCommits(Directory dir) throws IOException
    Returns all commit points that exist in the Directory. Normally, because the default is `KeepOnlyLastCommitDeletionPolicy`, there would be only one commit point. But if you're using a custom `IndexDeletionPolicy` then there could be many commits. Once you have a given commit, you can open a reader on it by calling `open(IndexCommit)` There must be at least one commit in the Directory, else this method throws `IndexNotFoundException`. Note that if a commit is in progress while this method is running, that commit may or may not be returned.
    Returns:
      a sorted list of `IndexCommit`s, from oldest to latest.
    Throws:
      `IOException`

  - ### indexExists

    public static boolean indexExists(Directory directory) throws IOException
    Returns `true` if an index likely exists at the specified directory. Note that if a corrupt index exists, or if an index in the process of committing
    Parameters:
      `directory` - the directory to check for an index
    Returns:
      `true` if an index exists; `false` otherwise
    Throws:
      `IOException`

  - ### directory

    public final Directory directory()
    Returns the directory this index resides in.

  - ### doOpenIfChanged

    protected abstract DirectoryReader doOpenIfChanged() throws IOException
    Implement this method to support `openIfChanged(DirectoryReader)`. If this reader does not support reopen, return `null`, so client code is happy. This should be consistent with `isCurrent()` (should always return `true`) if reopen is not supported.
    Returns:
      null if there are no changes; else, a new DirectoryReader instance.
    Throws:
      `IOException` - if there is a low-level IO error

  - ### doOpenIfChanged

    protected abstract DirectoryReader doOpenIfChanged(ExecutorService executorService) throws IOException
    Implement this method to support `openIfChanged(DirectoryReader)`. If this reader does not support reopen, return `null`, so client code is happy. This should be consistent with `isCurrent()` (should always return `true`) if reopen is not supported. ExecutorService provides intra-opening concurrency.
    Returns:
      null if there are no changes; else, a new DirectoryReader instance.
    Throws:
      `IOException` - if there is a low-level IO error

  - ### doOpenIfChanged

    protected abstract DirectoryReader doOpenIfChanged(IndexCommit commit) throws IOException
    Implement this method to support `openIfChanged(DirectoryReader,IndexCommit)`. If this reader does not support reopen from a specific `IndexCommit`, throw `UnsupportedOperationException`.
    Returns:
      null if there are no changes; else, a new DirectoryReader instance.
    Throws:
      `IOException` - if there is a low-level IO error

  - ### doOpenIfChanged

    protected abstract DirectoryReader doOpenIfChanged(IndexCommit commit, ExecutorService executorService) throws IOException
    Implement this method to support `openIfChanged(DirectoryReader,IndexCommit)`. If this reader does not support reopen from a specific `IndexCommit`, throw `UnsupportedOperationException`. ExecutorService provides intra-opening concurrency.
    Returns:
      null if there are no changes; else, a new DirectoryReader instance.
    Throws:
      `IOException` - if there is a low-level IO error

  - ### doOpenIfChanged

    protected abstract DirectoryReader doOpenIfChanged(IndexWriter writer, boolean applyAllDeletes) throws IOException
    Implement this method to support `openIfChanged(DirectoryReader,IndexWriter,boolean)`. If this reader does not support reopen from `IndexWriter`, throw `UnsupportedOperationException`.
    Returns:
      null if there are no changes; else, a new DirectoryReader instance.
    Throws:
      `IOException` - if there is a low-level IO error

  - ### doOpenIfChanged

    protected abstract DirectoryReader doOpenIfChanged(IndexWriter writer, boolean applyAllDeletes, ExecutorService executorService) throws IOException
    Implement this method to support `openIfChanged(DirectoryReader,IndexWriter,boolean)`. If this reader does not support reopen from `IndexWriter`, throw `UnsupportedOperationException`. ExecutorService used to open segment readers in parallel.
    Returns:
      null if there are no changes; else, a new DirectoryReader instance.
    Throws:
      `IOException` - if there is a low-level IO error

  - ### getVersion

    public abstract long getVersion()
    Version number when this IndexReader was opened.

    This method returns the version recorded in the commit that the reader opened. This version is advanced every time a change is made with `IndexWriter`.

  - ### isCurrent

    public abstract boolean isCurrent() throws IOException
    Check whether any new changes have occurred to the index since this reader was opened.

    If this reader was created by calling `open(org.apache.lucene.store.Directory)`, then this method checks if any further commits (see `IndexWriter.commit()`) have occurred in the directory.

    If instead this reader is a near real-time reader (ie, obtained by a call to `open(IndexWriter)`, or by calling `openIfChanged(org.apache.lucene.index.DirectoryReader)` on a near real-time reader), then this method checks if either a new commit has occurred, or any new uncommitted changes have taken place via the writer. Note that even if the writer has only performed merging, this method will still return false.

    In any event, if this returns false, you should call `openIfChanged(org.apache.lucene.index.DirectoryReader)` to get a new reader that sees the changes.

    Throws:
      `IOException` - if there is a low-level IO error

  - ### getIndexCommit

    public abstract IndexCommit getIndexCommit() throws IOException
    Expert: return the IndexCommit that this reader has opened.
    Throws:
      `IOException`
    WARNING: This API is experimental and might change in incompatible ways in the next release.