|
11 | 11 |
|
12 | 12 | import org.apache.lucene.codecs.Codec; |
13 | 13 | import org.apache.lucene.codecs.DocValuesFormat; |
| 14 | +import org.apache.lucene.codecs.lucene90.Lucene90DocValuesFormat; |
14 | 15 | import org.apache.lucene.document.BinaryDocValuesField; |
15 | 16 | import org.apache.lucene.document.Document; |
16 | 17 | import org.apache.lucene.document.NumericDocValuesField; |
|
21 | 22 | import org.apache.lucene.index.DocValues; |
22 | 23 | import org.apache.lucene.index.IndexWriter; |
23 | 24 | import org.apache.lucene.index.IndexWriterConfig; |
| 25 | +import org.apache.lucene.index.IndexableField; |
| 26 | +import org.apache.lucene.index.LeafReader; |
24 | 27 | import org.apache.lucene.index.LogByteSizeMergePolicy; |
| 28 | +import org.apache.lucene.index.NumericDocValues; |
| 29 | +import org.apache.lucene.index.SortedNumericDocValues; |
25 | 30 | import org.apache.lucene.search.Sort; |
26 | 31 | import org.apache.lucene.search.SortField; |
27 | 32 | import org.apache.lucene.search.SortedNumericSortField; |
28 | 33 | import org.apache.lucene.util.BytesRef; |
29 | 34 | import org.elasticsearch.cluster.metadata.DataStream; |
| 35 | +import org.elasticsearch.common.Randomness; |
30 | 36 | import org.elasticsearch.index.codec.Elasticsearch900Lucene101Codec; |
31 | 37 | import org.elasticsearch.index.codec.tsdb.ES87TSDBDocValuesFormatTests; |
32 | 38 |
|
| 39 | +import java.io.IOException; |
| 40 | +import java.util.ArrayList; |
33 | 41 | import java.util.Arrays; |
| 42 | +import java.util.List; |
34 | 43 | import java.util.Locale; |
| 44 | +import java.util.function.Supplier; |
35 | 45 |
|
36 | 46 | public class ES819TSDBDocValuesFormatTests extends ES87TSDBDocValuesFormatTests { |
37 | 47 |
|
@@ -514,6 +524,114 @@ public void testWithNoValueMultiValue() throws Exception { |
514 | 524 | } |
515 | 525 | } |
516 | 526 |
|
| 527 | + public void testAddIndices() throws IOException { |
| 528 | + String timestampField = "@timestamp"; |
| 529 | + String hostnameField = "host.name"; |
| 530 | + Supplier<IndexWriterConfig> indexConfigWithRandomDVFormat = () -> { |
| 531 | + IndexWriterConfig config = getTimeSeriesIndexWriterConfig(hostnameField, timestampField); |
| 532 | + DocValuesFormat dvFormat = switch (random().nextInt(3)) { |
| 533 | + case 0 -> new ES87TSDBDocValuesFormatTests.TestES87TSDBDocValuesFormat(random().nextInt(4, 16)); |
| 534 | + case 1 -> new ES819TSDBDocValuesFormat(); |
| 535 | + case 2 -> new Lucene90DocValuesFormat(); |
| 536 | + default -> throw new AssertionError("unknown option"); |
| 537 | + }; |
| 538 | + config.setCodec(new Elasticsearch900Lucene101Codec() { |
| 539 | + @Override |
| 540 | + public DocValuesFormat getDocValuesFormatForField(String field) { |
| 541 | + return dvFormat; |
| 542 | + } |
| 543 | + }); |
| 544 | + return config; |
| 545 | + }; |
| 546 | + try (var source1 = newDirectory(); var source2 = newDirectory(); var singleDir = newDirectory(); var mergeDir = newDirectory()) { |
| 547 | + try ( |
| 548 | + var writer1 = new IndexWriter(source1, indexConfigWithRandomDVFormat.get()); |
| 549 | + var writer2 = new IndexWriter(source2, indexConfigWithRandomDVFormat.get()); |
| 550 | + var singleWriter = new IndexWriter(singleDir, indexConfigWithRandomDVFormat.get()) |
| 551 | + ) { |
| 552 | + int numDocs = 1 + random().nextInt(1_000); |
| 553 | + long timestamp = random().nextLong(1000_000L); |
| 554 | + for (int i = 0; i < numDocs; i++) { |
| 555 | + List<IndexableField> fields = new ArrayList<>(); |
| 556 | + String hostName = String.format(Locale.ROOT, "host-%d", random().nextInt(5)); |
| 557 | + timestamp += 1 + random().nextInt(1_000); |
| 558 | + fields.add(new SortedDocValuesField(hostnameField, new BytesRef(hostName))); |
| 559 | + fields.add(new SortedNumericDocValuesField(timestampField, timestamp)); |
| 560 | + final IndexWriter splitWriter = random().nextBoolean() ? writer1 : writer2; |
| 561 | + if (random().nextBoolean()) { |
| 562 | + fields.add(new SortedNumericDocValuesField("gets", random().nextLong(1000_000L))); |
| 563 | + } else { |
| 564 | + fields.add(new SortedNumericDocValuesField("posts", random().nextLong(1000_000L))); |
| 565 | + } |
| 566 | + fields.add(new NumericDocValuesField("memory", random().nextLong(1000_000L))); |
| 567 | + Randomness.shuffle(fields); |
| 568 | + splitWriter.addDocument(fields); |
| 569 | + if (random().nextInt(100) <= 5) { |
| 570 | + splitWriter.commit(); |
| 571 | + } |
| 572 | + // add to the single writer |
| 573 | + singleWriter.addDocument(fields); |
| 574 | + if (random().nextInt(100) <= 5) { |
| 575 | + singleWriter.commit(); |
| 576 | + } |
| 577 | + } |
| 578 | + if (random().nextBoolean()) { |
| 579 | + writer1.forceMerge(1); |
| 580 | + } |
| 581 | + if (random().nextBoolean()) { |
| 582 | + writer2.forceMerge(1); |
| 583 | + } |
| 584 | + singleWriter.commit(); |
| 585 | + singleWriter.forceMerge(1); |
| 586 | + } |
| 587 | + try (var mergeWriter = new IndexWriter(mergeDir, getTimeSeriesIndexWriterConfig(hostnameField, timestampField))) { |
| 588 | + mergeWriter.addIndexes(source1, source2); |
| 589 | + mergeWriter.forceMerge(1); |
| 590 | + } |
| 591 | + try (var reader1 = DirectoryReader.open(singleDir); var reader2 = DirectoryReader.open(mergeDir)) { |
| 592 | + assertEquals(reader1.maxDoc(), reader2.maxDoc()); |
| 593 | + assertEquals(1, reader1.leaves().size()); |
| 594 | + assertEquals(1, reader2.leaves().size()); |
| 595 | + for (int i = 0; i < reader1.leaves().size(); i++) { |
| 596 | + LeafReader leaf1 = reader1.leaves().get(i).reader(); |
| 597 | + LeafReader leaf2 = reader2.leaves().get(i).reader(); |
| 598 | + duelAssertNumericField(leaf1, leaf2, "gets"); |
| 599 | + duelAssertNumericField(leaf1, leaf2, "posts"); |
| 600 | + duelAssertNumericField(leaf1, leaf2, "memory"); |
| 601 | + duelAssertNumericField(leaf1, leaf2, "@timestamp"); |
| 602 | + } |
| 603 | + } |
| 604 | + } |
| 605 | + } |
| 606 | + |
| 607 | + static void duelAssertNumericField(LeafReader reader1, LeafReader reader2, String fieldName) throws IOException { |
| 608 | + SortedNumericDocValues sdv1 = reader1.getSortedNumericDocValues(fieldName); |
| 609 | + SortedNumericDocValues sdv2 = reader2.getSortedNumericDocValues(fieldName); |
| 610 | + NumericDocValues dv1; |
| 611 | + NumericDocValues dv2; |
| 612 | + if (sdv1 != null) { |
| 613 | + dv1 = DocValues.unwrapSingleton(sdv1); |
| 614 | + assertNotNull(sdv2); |
| 615 | + dv2 = DocValues.unwrapSingleton(sdv2); |
| 616 | + assertNotNull(dv1); |
| 617 | + assertNotNull(dv2); |
| 618 | + } else { |
| 619 | + assertNull(sdv2); |
| 620 | + dv1 = reader1.getNumericDocValues(fieldName); |
| 621 | + dv2 = reader2.getNumericDocValues(fieldName); |
| 622 | + if (dv1 == null) { |
| 623 | + assertNull(dv2); |
| 624 | + return; |
| 625 | + } |
| 626 | + } |
| 627 | + while (dv1.nextDoc() != NumericDocValues.NO_MORE_DOCS) { |
| 628 | + assertNotEquals(NumericDocValues.NO_MORE_DOCS, dv2.nextDoc()); |
| 629 | + assertEquals(dv1.docID(), dv2.docID()); |
| 630 | + assertEquals(dv1.longValue(), dv2.longValue()); |
| 631 | + } |
| 632 | + assertEquals(NumericDocValues.NO_MORE_DOCS, dv2.nextDoc()); |
| 633 | + } |
| 634 | + |
517 | 635 | private IndexWriterConfig getTimeSeriesIndexWriterConfig(String hostnameField, String timestampField) { |
518 | 636 | var config = new IndexWriterConfig(); |
519 | 637 | config.setIndexSort( |
|
0 commit comments