From b3bfd453f5ae1e257ee687601b0e7d7c4bc7c283 Mon Sep 17 00:00:00 2001 From: jimczi Date: Tue, 11 Jun 2019 09:16:58 +0200 Subject: [PATCH] Handle empty terms index in TermsSliceQuery #40741 introduced a merge policy that can drop the postings for the `_id` field on soft deleted documents. The TermsSliceQuery assumes that every document has has an entry in the postings for that field so it doesn't check if the terms index exists or not. This change fixes this bug by checking if the terms index for the `_id` field is null and ignore the segment entirely if it's the case. This should be harmless since segments without an `_id` terms index should only contain soft deleted documents. Closes #42996 --- .../search/slice/TermsSliceQuery.java | 3 +++ .../search/slice/TermsSliceQueryTests.java | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/server/src/main/java/org/elasticsearch/search/slice/TermsSliceQuery.java b/server/src/main/java/org/elasticsearch/search/slice/TermsSliceQuery.java index 52ac72d01b778..1ec3479424193 100644 --- a/server/src/main/java/org/elasticsearch/search/slice/TermsSliceQuery.java +++ b/server/src/main/java/org/elasticsearch/search/slice/TermsSliceQuery.java @@ -78,6 +78,9 @@ public boolean isCacheable(LeafReaderContext ctx) { private DocIdSet build(LeafReader reader) throws IOException { final DocIdSetBuilder builder = new DocIdSetBuilder(reader.maxDoc()); final Terms terms = reader.terms(getField()); + if (terms == null) { + return DocIdSet.EMPTY; + } final TermsEnum te = terms.iterator(); PostingsEnum docsEnum = null; for (BytesRef term = te.next(); term != null; term = te.next()) { diff --git a/server/src/test/java/org/elasticsearch/search/slice/TermsSliceQueryTests.java b/server/src/test/java/org/elasticsearch/search/slice/TermsSliceQueryTests.java index 881dc6f9587af..96fb508f7ff0d 100644 --- a/server/src/test/java/org/elasticsearch/search/slice/TermsSliceQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/slice/TermsSliceQueryTests.java @@ -62,6 +62,24 @@ public void testBasics() { QueryUtils.checkUnequal(query1, query4); } + public void testEmpty() throws Exception { + final Directory dir = newDirectory(); + final RandomIndexWriter w = new RandomIndexWriter(random(), dir, new KeywordAnalyzer()); + for (int i = 0; i < 10; ++i) { + Document doc = new Document(); + doc.add(new StringField("field", Integer.toString(i), Field.Store.YES)); + w.addDocument(doc); + } + final IndexReader reader = w.getReader(); + final IndexSearcher searcher = newSearcher(reader); + TermsSliceQuery query = + new TermsSliceQuery("unknown", 1, 1); + assertThat(searcher.count(query), equalTo(0)); + w.close(); + reader.close(); + dir.close(); + } + public void testSearch() throws Exception { final int numDocs = randomIntBetween(100, 200); final Directory dir = newDirectory();