apache / apache/lucene

Index Segment without DocValues May Cause Search to Fail [LUCENE-9755]

Open
#10,794 1 comment 0 reactions 0 assignees View on GitHub
affects-version:8.3.1 affects-version:8.8 affects-version:8.x legacy-jira-label:docValues legacy-jira-label:sorting legacy-jira-priority:Minor module:core/search type:bug
Dominant language
Java
Stars
3.6k
Forks
1.4k
Avg merge
2d 11h
Merged PRs (30d)
88

Description

Not sure if this can be considered a bug, but it is certainly a caveat that may slip through testing due to its nature.

Consider the following scenario:
- all documents in the index have a field "numfield" indexed as IntPoint
- in addition, SOME of those documents are also indexed with a SortedNumericDocValuesField using the same "numfield" name

The documents without the DocValues cannot be matched from any queries that involve sorting, so we save some space by omitting the DocValues for those documents.

This works perfectly fine, unless
- the index contains a segment that only contains documents without the DocValues

In this case, running a query that sorts by "numfield" will throw the following exception:
```
java.lang.IllegalStateException: unexpected docvalues type NONE for field 'numfield' (expected one of [SORTED_NUMERIC, NUMERIC]). Re-index with correct docvalues type.
   at org.apache.lucene.index.DocValues.checkField(DocValues.java:317)
   at org.apache.lucene.index.DocValues.getSortedNumeric(DocValues.java:389)
   at org.apache.lucene.search.SortedNumericSortField$3.getNumericDocValues(SortedNumericSortField.java:159)
   at org.apache.lucene.search.FieldComparator$NumericComparator.doSetNextReader(FieldComparator.java:155)
```
I have included a minimal example program that demonstrates the issue. This will
- create an index with two documents, each having "numfield" indexed
- add a DocValuesField "numfield" only for the first document
- force the two documents into separate index segments
- run a query that matches only the first document and sorts by "numfield"

This results in the aforementioned exception.

When removing the following lines from the code:

```java
if (i==docCount/2) {
iw.commit();
}
```

both documents get added to the same segment. When re-running the code creating with a single index segment, the query works fine.

Tested with Lucene 8.3.1 and 8.8.0  .

Like I said, this may not be considered a bug. But it has slipped through our testing because the existence of such a DocValues-free segment is such a rare and short-lived event.

We can avoid this issue in the future by using a different field name for the DocValuesField. But for our production systems we have to patch DocValues.checkField() to suppress the IllegalStateException as reindexing is not an option right now.

---
Migrated from [LUCENE-9755](https://issues.apache.org/jira/browse/LUCENE-9755) by Thomas Hecker, updated Feb 11 2021
Attachments: [DocValuesTest.java](https://apache.github.io/lucene-jira-archive/attachments/LUCENE-9755/DocValuesTest.java)

Contributor guide

Open the contributing guide

Research direction

Start with the attached DocValuesTest.java reproducer and trace the failure through DocValues.checkField(), DocValues.getSortedNumeric(), SortedNumericSortField, and FieldComparator. Run the example against the affected Lucene versions, then add regression coverage showing that sorting does not fail when a segment lacks DocValues for the field.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
search
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.