-
Notifications
You must be signed in to change notification settings - Fork 24.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
If a match interval query ends up with no tokens after analysis, we return an IntervalsSource that produces an empty interval iterator. This empty iterator previously always reported its current doc id as NO_MORE_DOCS. However, unpositioned DocIdSetIterators should report their doc id as -1, so this broke the API contract, which could lead to exceptions when an empty interval query was combined in a conjunction. This commit fixes the empty interval implementation so that it returns -1 when unpositioned. Fixes #89789
- Loading branch information
1 parent
635de5e
commit 5fb9f1c
Showing
3 changed files
with
115 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
pr: 89962 | ||
summary: Empty intervals needs to start in position -1 | ||
area: Search | ||
type: bug | ||
issues: | ||
- 89789 |
104 changes: 104 additions & 0 deletions
104
server/src/internalClusterTest/java/org/elasticsearch/search/query/IntervalQueriesIT.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
package org.elasticsearch.search.query; | ||
|
||
import org.apache.lucene.analysis.Analyzer; | ||
import org.apache.lucene.analysis.TokenStream; | ||
import org.apache.lucene.analysis.Tokenizer; | ||
import org.apache.lucene.analysis.core.KeywordTokenizer; | ||
import org.elasticsearch.action.search.SearchResponse; | ||
import org.elasticsearch.index.analysis.AnalyzerProvider; | ||
import org.elasticsearch.index.analysis.AnalyzerScope; | ||
import org.elasticsearch.index.query.IntervalQueryBuilder; | ||
import org.elasticsearch.index.query.IntervalsSourceProvider; | ||
import org.elasticsearch.indices.analysis.AnalysisModule; | ||
import org.elasticsearch.plugins.AnalysisPlugin; | ||
import org.elasticsearch.plugins.Plugin; | ||
import org.elasticsearch.test.ESIntegTestCase; | ||
import org.elasticsearch.test.InternalSettingsPlugin; | ||
|
||
import java.io.IOException; | ||
import java.util.Arrays; | ||
import java.util.Collection; | ||
import java.util.Map; | ||
|
||
import static java.util.Collections.singletonMap; | ||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; | ||
|
||
public class IntervalQueriesIT extends ESIntegTestCase { | ||
|
||
@Override | ||
protected Collection<Class<? extends Plugin>> nodePlugins() { | ||
return Arrays.asList(InternalSettingsPlugin.class, MockAnalysisPlugin.class); | ||
} | ||
|
||
public void testEmptyIntervalsWithNestedMappings() throws InterruptedException { | ||
assertAcked(prepareCreate("nested").setMapping(""" | ||
{ "_doc" : { | ||
"properties" : { | ||
"empty_text" : { "type" : "text", "analyzer" : "empty" }, | ||
"text" : { "type" : "text" }, | ||
"nested" : { "type" : "nested", "properties" : { "nt" : { "type" : "text" } } } | ||
} | ||
}} | ||
""")); | ||
|
||
indexRandom( | ||
true, | ||
client().prepareIndex("nested").setId("1").setSource("text", "the quick brown fox jumps"), | ||
client().prepareIndex("nested").setId("2").setSource("text", "quick brown"), | ||
client().prepareIndex("nested").setId("3").setSource("text", "quick") | ||
); | ||
|
||
SearchResponse resp = client().prepareSearch("nested") | ||
.setQuery( | ||
new IntervalQueryBuilder("empty_text", new IntervalsSourceProvider.Match("an empty query", 0, true, null, null, null)) | ||
) | ||
.get(); | ||
assertEquals(0, resp.getFailedShards()); | ||
} | ||
|
||
private static class EmptyAnalyzer extends Analyzer { | ||
|
||
@Override | ||
protected TokenStreamComponents createComponents(String fieldName) { | ||
Tokenizer source = new KeywordTokenizer(); | ||
TokenStream sink = new TokenStream() { | ||
@Override | ||
public boolean incrementToken() throws IOException { | ||
return false; | ||
} | ||
}; | ||
return new TokenStreamComponents(source, sink); | ||
} | ||
} | ||
|
||
public static class MockAnalysisPlugin extends Plugin implements AnalysisPlugin { | ||
|
||
@Override | ||
public Map<String, AnalysisModule.AnalysisProvider<AnalyzerProvider<? extends Analyzer>>> getAnalyzers() { | ||
return singletonMap("empty", (indexSettings, environment, name, settings) -> new AnalyzerProvider<>() { | ||
@Override | ||
public String name() { | ||
return "empty"; | ||
} | ||
|
||
@Override | ||
public AnalyzerScope scope() { | ||
return AnalyzerScope.GLOBAL; | ||
} | ||
|
||
@Override | ||
public Analyzer get() { | ||
return new EmptyAnalyzer(); | ||
} | ||
}); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters