This is an automated email from the ASF dual-hosted git repository.

dsmiley pushed a commit to branch branch_9x
in repository https://gitbox.apache.org/repos/asf/solr.git

commit cfbaf00511337b3c4789486b4e0437cfa51efcfa
Author: David Smiley <[email protected]>
AuthorDate: Wed Jul 8 13:15:09 2026 -0400

    SOLR-17170: Support block/nested docs with index sorting (#4619)
    
    (cherry picked from commit 595f760b3b56ae17f231e1b0ad1f4b24f8cdd47e)
---
 .../unreleased/SOLR-17170-indexSortBlocks.yml      |  8 +++++++
 .../java/org/apache/solr/schema/IndexSchema.java   |  1 +
 .../org/apache/solr/update/SolrIndexConfig.java    | 10 ++++++++
 .../org/apache/solr/cloud/TestSegmentSorting.java  | 27 ++++++++++++++++++++++
 .../apache/solr/update/SolrIndexConfigTest.java    |  6 +++++
 5 files changed, 52 insertions(+)

diff --git a/changelog/unreleased/SOLR-17170-indexSortBlocks.yml 
b/changelog/unreleased/SOLR-17170-indexSortBlocks.yml
new file mode 100644
index 00000000000..5f9be49f36f
--- /dev/null
+++ b/changelog/unreleased/SOLR-17170-indexSortBlocks.yml
@@ -0,0 +1,8 @@
+title: >
+  Support block / nested-docs with index sorting
+type: added
+authors:
+  - name: David Smiley
+links:
+  - name: SOLR-17170
+    url: https://issues.apache.org/jira/browse/SOLR-17170
diff --git a/solr/core/src/java/org/apache/solr/schema/IndexSchema.java 
b/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
index a20c17867b1..9b1a58be7f1 100644
--- a/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
+++ b/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
@@ -107,6 +107,7 @@ public class IndexSchema {
   public static final String NEST_PARENT_FIELD_NAME = "_nest_parent_";
   public static final String NEST_PATH_FIELD_NAME = "_nest_path_";
   public static final String NESTED_VECTORS_PSEUDO_FIELD_NAME = 
"_nested_vectors_";
+  public static final String IS_ROOT_FIELD_NAME = "_is_root_";
   public static final String REQUIRED = "required";
   public static final String SCHEMA = "schema";
   public static final String SIMILARITY = "similarity";
diff --git a/solr/core/src/java/org/apache/solr/update/SolrIndexConfig.java 
b/solr/core/src/java/org/apache/solr/update/SolrIndexConfig.java
index 94c5e63aa37..70b01aa0679 100644
--- a/solr/core/src/java/org/apache/solr/update/SolrIndexConfig.java
+++ b/solr/core/src/java/org/apache/solr/update/SolrIndexConfig.java
@@ -31,6 +31,7 @@ import org.apache.lucene.index.MergePolicy;
 import org.apache.lucene.index.MergeScheduler;
 import org.apache.lucene.search.Sort;
 import org.apache.lucene.util.InfoStream;
+import org.apache.lucene.util.Version;
 import org.apache.solr.common.ConfigNode;
 import org.apache.solr.common.MapSerializable;
 import org.apache.solr.common.util.NamedList;
@@ -270,6 +271,15 @@ public class SolrIndexConfig implements MapSerializable {
       iwc.setIndexSort(indexSort);
     }
 
+    if (iwc.getIndexSort() != null
+        && schema.isUsableForChildDocs()
+        && 
core.getSolrConfig().luceneMatchVersion.onOrAfter(Version.LUCENE_9_12_3)) {
+      // Lucene 9.12.3 is when this branch gained parent-field support; earlier
+      // luceneMatchVersion settings didn't set it. This version check allows 
an upgrading
+      // user to continue to do index sorting.
+      iwc.setParentField(IndexSchema.IS_ROOT_FIELD_NAME);
+    }
+
     iwc.setUseCompoundFile(useCompoundFile);
 
     if (mergedSegmentWarmerInfo != null) {
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestSegmentSorting.java 
b/solr/core/src/test/org/apache/solr/cloud/TestSegmentSorting.java
index 5a4b24c897a..c79ca7b98d9 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestSegmentSorting.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestSegmentSorting.java
@@ -97,6 +97,33 @@ public class TestSegmentSorting extends SolrCloudTestCase {
     // add some documents, then optimize to get merged-sorted segments
     tstes.addDocuments(collectionName, cloudSolrClient, 10, 10, true);
 
+    // add block docs with children having different sort values than parent;
+    // Lucene sorts by parent values only, so block integrity must be preserved
+    for (int i = 0; i < 5; i++) {
+      int parentTs = random().nextInt(60);
+      int childTs = random().nextInt(60);
+      cloudSolrClient.add(
+          collectionName,
+          sdoc(
+              "id",
+              10000 + i,
+              "timestamp_i_dvo",
+              parentTs,
+              "children",
+              sdocs(sdoc("id", 10100 + i, "timestamp_i_dvo", childTs))));
+    }
+    cloudSolrClient.commit(collectionName);
+    cloudSolrClient.optimize(collectionName);
+    // verify block integrity: each child still belongs to its parent after 
merge-sorting
+    for (int i = 0; i < 5; i++) {
+      assertEquals(
+          2,
+          cloudSolrClient
+              .query(collectionName, params("q", "_root_:" + (10000 + i)))
+              .getResults()
+              .getNumFound());
+    }
+
     // CommonParams.SEGMENT_TERMINATE_EARLY parameter intentionally absent
     tstes.queryTimestampDescending(collectionName, cloudSolrClient);
 
diff --git a/solr/core/src/test/org/apache/solr/update/SolrIndexConfigTest.java 
b/solr/core/src/test/org/apache/solr/update/SolrIndexConfigTest.java
index 072835c596e..2ac975e7bb7 100644
--- a/solr/core/src/test/org/apache/solr/update/SolrIndexConfigTest.java
+++ b/solr/core/src/test/org/apache/solr/update/SolrIndexConfigTest.java
@@ -123,6 +123,7 @@ public class SolrIndexConfigTest extends SolrTestCaseJ4 {
     assertEquals("ms.maxMergeCount", 987, ms.getMaxMergeCount());
     assertEquals("ms.maxThreadCount", 42, ms.getMaxThreadCount());
     assertTrue("ms.isAutoIOThrottle", ms.getAutoIOThrottle());
+    assertNull("parentField should not be set without index sort", 
iwc.getParentField());
   }
 
   @Test
@@ -174,6 +175,11 @@ public class SolrIndexConfigTest extends SolrTestCaseJ4 {
     }
     final Sort actual = sortingMergePolicy.getSort();
     assertEquals("SortingMergePolicy.getSort", expected, actual);
+    assertEquals("indexSort on IWC", expected, iwc.getIndexSort());
+    assertEquals(
+        "parentField should be set when indexSort is configured",
+        IndexSchema.IS_ROOT_FIELD_NAME,
+        iwc.getParentField());
   }
 
   public void testMergeOnFlushMPSolrIndexConfigCreation() throws Exception {

Reply via email to