Skip to content

Commit ec51d45

Browse files
Merge branch 'main' into index-version-compatibility-IT
2 parents 469b97f + 848a678 commit ec51d45

File tree

6 files changed

+130
-37
lines changed

6 files changed

+130
-37
lines changed

docs/changelog/125881.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 125881
2+
summary: Fixes a invalid warning from being issued when restoring a system data stream from a snapshot.
3+
area: "Data streams"
4+
type: bug
5+
issues: []

docs/reference/query-languages/esql/limitations.md

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,54 @@ mapped_pages:
1010

1111
## Result set size limit [esql-max-rows]
1212

13-
By default, an {{esql}} query returns up to 1000 rows. You can increase the number of rows up to 10,000 using the [`LIMIT`](/reference/query-languages/esql/esql-commands.md#esql-limit) command. Queries do not return more than 10,000 rows, regardless of the `LIMIT` command’s value.
13+
By default, an {{esql}} query returns up to 1,000 rows. You can increase the number of rows up to 10,000 using the [`LIMIT`](/reference/query-languages/esql/esql-commands.md#esql-limit) command.
1414

15-
This limit only applies to the number of rows that are retrieved by the query. Queries and aggregations run on the full data set.
15+
For instance,
16+
```esql
17+
FROM index | WHERE field = "value"
18+
```
19+
is equivalent to:
20+
```esql
21+
FROM index | WHERE field = "value" | LIMIT 1000
22+
```
23+
24+
Queries do not return more than 10,000 rows, regardless of the `LIMIT` command’s value. This is a configurable upper limit.
1625

1726
To overcome this limitation:
1827

1928
* Reduce the result set size by modifying the query to only return relevant data. Use [`WHERE`](/reference/query-languages/esql/esql-commands.md#esql-where) to select a smaller subset of the data.
2029
* Shift any post-query processing to the query itself. You can use the {{esql}} [`STATS`](/reference/query-languages/esql/esql-commands.md#esql-stats-by) command to aggregate data in the query.
2130

31+
The upper limit only applies to the number of rows that are output by the query, not to the number of documents it processes: the query runs on the full data set.
32+
33+
Consider the following two queries:
34+
```esql
35+
FROM index | WHERE field0 == "value" | LIMIT 20000
36+
```
37+
and
38+
```esql
39+
FROM index | STATS AVG(field1) BY field2 | LIMIT 20000
40+
```
41+
42+
In both cases, the filtering by `field0` in the first query or the grouping by `field2` in the second is applied over all the documents present in the `index`, irrespective of their number or indexes size. However, both queries will return at most 10,000 rows, even if there were more rows available to return.
43+
2244
The default and maximum limits can be changed using these dynamic cluster settings:
2345

2446
* `esql.query.result_truncation_default_size`
2547
* `esql.query.result_truncation_max_size`
2648

49+
However, doing so involves trade-offs. A larger result-set involves a higher memory pressure and increased processing times; the internode traffic within and across clusters can also increase.
50+
51+
These limitations are similar to those enforced by the [search API for pagination](/reference/elasticsearch/rest-apis/paginate-search-results.md#paginate-search-results).
52+
53+
| Functionality | Search | {{esql}} |
54+
|----------------------------------|-------------------------|-------------------------------------------|
55+
| Results returned by default | 10 | 1.000 |
56+
| Default upper limit | 10,000 | 10,000 |
57+
| Specify number of results | `size` | `LIMIT` |
58+
| Change default number of results | n/a | esql.query.result_truncation_default_size |
59+
| Change default upper limit | index-max-result-window | esql.query.result_truncation_max_size |
60+
2761

2862
## Field types [esql-supported-types]
2963

docs/reference/query-languages/query-dsl/query-dsl-script-score-query.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Final relevance scores from the `script_score` query cannot be negative. To supp
4747

4848

4949
`min_score`
50-
: (Optional, float) Documents with a score lower than this floating point number are excluded from the search results.
50+
: (Optional, float) Documents with a score lower than this floating point number are excluded from search results and results collected by aggregations.
5151

5252
`boost`
5353
: (Optional, float) Documents' scores produced by `script` are multiplied by `boost` to produce final documents' scores. Defaults to `1.0`.

server/src/main/java/org/elasticsearch/index/codec/tsdb/ES87TSDBDocValuesProducer.java

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.apache.lucene.index.SortedNumericDocValues;
3030
import org.apache.lucene.index.SortedSetDocValues;
3131
import org.apache.lucene.index.TermsEnum;
32+
import org.apache.lucene.internal.hppc.IntObjectHashMap;
3233
import org.apache.lucene.search.DocIdSetIterator;
3334
import org.apache.lucene.store.ByteArrayDataInput;
3435
import org.apache.lucene.store.ChecksumIndexInput;
@@ -43,33 +44,31 @@
4344
import org.elasticsearch.core.IOUtils;
4445

4546
import java.io.IOException;
46-
import java.util.HashMap;
47-
import java.util.Map;
4847

4948
import static org.elasticsearch.index.codec.tsdb.ES87TSDBDocValuesFormat.SKIP_INDEX_JUMP_LENGTH_PER_LEVEL;
5049
import static org.elasticsearch.index.codec.tsdb.ES87TSDBDocValuesFormat.SKIP_INDEX_MAX_LEVEL;
5150
import static org.elasticsearch.index.codec.tsdb.ES87TSDBDocValuesFormat.TERMS_DICT_BLOCK_LZ4_SHIFT;
5251

5352
public class ES87TSDBDocValuesProducer extends DocValuesProducer {
54-
private final Map<String, NumericEntry> numerics;
55-
private final Map<String, BinaryEntry> binaries;
56-
private final Map<String, SortedEntry> sorted;
57-
private final Map<String, SortedSetEntry> sortedSets;
58-
private final Map<String, SortedNumericEntry> sortedNumerics;
59-
private final Map<String, DocValuesSkipperEntry> skippers;
53+
private final IntObjectHashMap<NumericEntry> numerics;
54+
private final IntObjectHashMap<BinaryEntry> binaries;
55+
private final IntObjectHashMap<SortedEntry> sorted;
56+
private final IntObjectHashMap<SortedSetEntry> sortedSets;
57+
private final IntObjectHashMap<SortedNumericEntry> sortedNumerics;
58+
private final IntObjectHashMap<DocValuesSkipperEntry> skippers;
6059
private final IndexInput data;
6160
private final int maxDoc;
6261
private final int version;
6362
private final boolean merging;
6463

6564
ES87TSDBDocValuesProducer(SegmentReadState state, String dataCodec, String dataExtension, String metaCodec, String metaExtension)
6665
throws IOException {
67-
this.numerics = new HashMap<>();
68-
this.binaries = new HashMap<>();
69-
this.sorted = new HashMap<>();
70-
this.sortedSets = new HashMap<>();
71-
this.sortedNumerics = new HashMap<>();
72-
this.skippers = new HashMap<>();
66+
this.numerics = new IntObjectHashMap<>();
67+
this.binaries = new IntObjectHashMap<>();
68+
this.sorted = new IntObjectHashMap<>();
69+
this.sortedSets = new IntObjectHashMap<>();
70+
this.sortedNumerics = new IntObjectHashMap<>();
71+
this.skippers = new IntObjectHashMap<>();
7372
this.maxDoc = state.segmentInfo.maxDoc();
7473
this.merging = false;
7574

@@ -130,12 +129,12 @@ public class ES87TSDBDocValuesProducer extends DocValuesProducer {
130129
}
131130

132131
private ES87TSDBDocValuesProducer(
133-
Map<String, NumericEntry> numerics,
134-
Map<String, BinaryEntry> binaries,
135-
Map<String, SortedEntry> sorted,
136-
Map<String, SortedSetEntry> sortedSets,
137-
Map<String, SortedNumericEntry> sortedNumerics,
138-
Map<String, DocValuesSkipperEntry> skippers,
132+
IntObjectHashMap<NumericEntry> numerics,
133+
IntObjectHashMap<BinaryEntry> binaries,
134+
IntObjectHashMap<SortedEntry> sorted,
135+
IntObjectHashMap<SortedSetEntry> sortedSets,
136+
IntObjectHashMap<SortedNumericEntry> sortedNumerics,
137+
IntObjectHashMap<DocValuesSkipperEntry> skippers,
139138
IndexInput data,
140139
int maxDoc,
141140
int version,
@@ -160,13 +159,13 @@ public DocValuesProducer getMergeInstance() {
160159

161160
@Override
162161
public NumericDocValues getNumeric(FieldInfo field) throws IOException {
163-
NumericEntry entry = numerics.get(field.name);
162+
NumericEntry entry = numerics.get(field.number);
164163
return getNumeric(entry, -1);
165164
}
166165

167166
@Override
168167
public BinaryDocValues getBinary(FieldInfo field) throws IOException {
169-
BinaryEntry entry = binaries.get(field.name);
168+
BinaryEntry entry = binaries.get(field.number);
170169
if (entry.docsWithFieldOffset == -2) {
171170
return DocValues.emptyBinary();
172171
}
@@ -320,7 +319,7 @@ public boolean advanceExact(int target) throws IOException {
320319

321320
@Override
322321
public SortedDocValues getSorted(FieldInfo field) throws IOException {
323-
SortedEntry entry = sorted.get(field.name);
322+
SortedEntry entry = sorted.get(field.number);
324323
return getSorted(entry);
325324
}
326325

@@ -675,13 +674,13 @@ public int docFreq() throws IOException {
675674

676675
@Override
677676
public SortedNumericDocValues getSortedNumeric(FieldInfo field) throws IOException {
678-
SortedNumericEntry entry = sortedNumerics.get(field.name);
677+
SortedNumericEntry entry = sortedNumerics.get(field.number);
679678
return getSortedNumeric(entry, -1);
680679
}
681680

682681
@Override
683682
public SortedSetDocValues getSortedSet(FieldInfo field) throws IOException {
684-
SortedSetEntry entry = sortedSets.get(field.name);
683+
SortedSetEntry entry = sortedSets.get(field.number);
685684
if (entry.singleValueEntry != null) {
686685
return DocValues.singleton(getSorted(entry.singleValueEntry));
687686
}
@@ -743,7 +742,7 @@ public long cost() {
743742

744743
@Override
745744
public DocValuesSkipper getSkipper(FieldInfo field) throws IOException {
746-
final DocValuesSkipperEntry entry = skippers.get(field.name);
745+
final DocValuesSkipperEntry entry = skippers.get(field.number);
747746

748747
final IndexInput input = data.slice("doc value skipper", entry.offset, entry.length);
749748
// Prefetch the first page of data. Following pages are expected to get prefetched through
@@ -869,18 +868,18 @@ private void readFields(IndexInput meta, FieldInfos infos) throws IOException {
869868
}
870869
byte type = meta.readByte();
871870
if (info.docValuesSkipIndexType() != DocValuesSkipIndexType.NONE) {
872-
skippers.put(info.name, readDocValueSkipperMeta(meta));
871+
skippers.put(info.number, readDocValueSkipperMeta(meta));
873872
}
874873
if (type == ES87TSDBDocValuesFormat.NUMERIC) {
875-
numerics.put(info.name, readNumeric(meta));
874+
numerics.put(info.number, readNumeric(meta));
876875
} else if (type == ES87TSDBDocValuesFormat.BINARY) {
877-
binaries.put(info.name, readBinary(meta));
876+
binaries.put(info.number, readBinary(meta));
878877
} else if (type == ES87TSDBDocValuesFormat.SORTED) {
879-
sorted.put(info.name, readSorted(meta));
878+
sorted.put(info.number, readSorted(meta));
880879
} else if (type == ES87TSDBDocValuesFormat.SORTED_SET) {
881-
sortedSets.put(info.name, readSortedSet(meta));
880+
sortedSets.put(info.number, readSortedSet(meta));
882881
} else if (type == ES87TSDBDocValuesFormat.SORTED_NUMERIC) {
883-
sortedNumerics.put(info.name, readSortedNumeric(meta));
882+
sortedNumerics.put(info.number, readSortedNumeric(meta));
884883
} else {
885884
throw new CorruptIndexException("invalid type: " + type, meta);
886885
}

server/src/main/java/org/elasticsearch/snapshots/RestoreService.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -539,9 +539,19 @@ private void validateDataStreamTemplatesExistAndWarnIfMissing(
539539
Set<String> templatePatterns = streams.filter(cit -> cit.getDataStreamTemplate() != null)
540540
.flatMap(cit -> cit.indexPatterns().stream())
541541
.collect(Collectors.toSet());
542+
warnIfIndexTemplateMissing(dataStreamsToRestore, templatePatterns, snapshotInfo);
543+
}
542544

543-
for (String name : dataStreamsToRestore.keySet()) {
544-
if (templatePatterns.stream().noneMatch(pattern -> Regex.simpleMatch(pattern, name))) {
545+
// Visible for testing
546+
static void warnIfIndexTemplateMissing(
547+
Map<String, DataStream> dataStreamsToRestore,
548+
Set<String> templatePatterns,
549+
SnapshotInfo snapshotInfo
550+
) {
551+
for (var entry : dataStreamsToRestore.entrySet()) {
552+
String name = entry.getKey();
553+
DataStream dataStream = entry.getValue();
554+
if (dataStream.isSystem() == false && templatePatterns.stream().noneMatch(pattern -> Regex.simpleMatch(pattern, name))) {
545555
String warningMessage = format(
546556
"Snapshot [%s] contains data stream [%s] but custer does not have a matching index template. This will cause"
547557
+ " rollover to fail until a matching index template is created",

server/src/test/java/org/elasticsearch/snapshots/RestoreServiceTests.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import java.util.Set;
3737
import java.util.concurrent.atomic.AtomicBoolean;
3838

39+
import static org.elasticsearch.core.Strings.format;
3940
import static org.hamcrest.Matchers.empty;
4041
import static org.hamcrest.Matchers.equalTo;
4142
import static org.mockito.ArgumentMatchers.any;
@@ -48,6 +49,50 @@
4849

4950
public class RestoreServiceTests extends ESTestCase {
5051

52+
/**
53+
* Test that {@link RestoreService#warnIfIndexTemplateMissing(Map, Set, SnapshotInfo)} does not warn for system
54+
* datastreams.
55+
*/
56+
public void testWarnIfIndexTemplateMissingSkipsSystemDataStreams() throws Exception {
57+
String dataStreamName = ".test-system-data-stream";
58+
String backingIndexName = DataStream.getDefaultBackingIndexName(dataStreamName, 1);
59+
List<Index> indices = List.of(new Index(backingIndexName, randomUUID()));
60+
61+
var dataStream = DataStream.builder(dataStreamName, indices).setSystem(true).setHidden(true).build();
62+
var dataStreamsToRestore = Map.of(dataStreamName, dataStream);
63+
var templatePatterns = Set.of("matches_none");
64+
var snapshotInfo = createSnapshotInfo(new Snapshot("repository", new SnapshotId("name", "uuid")), Boolean.FALSE);
65+
66+
RestoreService.warnIfIndexTemplateMissing(dataStreamsToRestore, templatePatterns, snapshotInfo);
67+
68+
ensureNoWarnings();
69+
}
70+
71+
/**
72+
* Test that {@link RestoreService#warnIfIndexTemplateMissing(Map, Set, SnapshotInfo)} warns for non-system datastreams.
73+
*/
74+
public void testWarnIfIndexTemplateMissing() throws Exception {
75+
String dataStreamName = ".test-system-data-stream";
76+
String backingIndexName = DataStream.getDefaultBackingIndexName(dataStreamName, 1);
77+
List<Index> indices = List.of(new Index(backingIndexName, randomUUID()));
78+
79+
var dataStream = DataStream.builder(dataStreamName, indices).build();
80+
var dataStreamsToRestore = Map.of(dataStreamName, dataStream);
81+
var templatePatterns = Set.of("matches_none");
82+
var snapshotInfo = createSnapshotInfo(new Snapshot("repository", new SnapshotId("name", "uuid")), Boolean.FALSE);
83+
84+
RestoreService.warnIfIndexTemplateMissing(dataStreamsToRestore, templatePatterns, snapshotInfo);
85+
86+
assertWarnings(
87+
format(
88+
"Snapshot [%s] contains data stream [%s] but custer does not have a matching index template. This will cause"
89+
+ " rollover to fail until a matching index template is created",
90+
snapshotInfo.snapshotId(),
91+
dataStreamName
92+
)
93+
);
94+
}
95+
5196
public void testUpdateDataStream() {
5297
long now = System.currentTimeMillis();
5398
String dataStreamName = "data-stream-1";

0 commit comments

Comments
 (0)