diff --git a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java index d4d1f64bcda..bd90b5eb0a0 100644 --- a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java +++ b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java @@ -228,17 +228,30 @@ private Collector buildAndRunCollectorChain( if (cmd.getSegmentTerminateEarly()) { final Sort cmdSort = cmd.getSort(); final int cmdLen = cmd.getLen(); + + final Sort indexOrMergeSort; final Sort mergeSort = core.getSolrCoreState().getMergePolicySort(); + final Sort indexSort; + { + final String indexSortStr = core.getSolrConfig().indexConfig.indexSort; + if (indexSortStr != null) { + indexSort = SortSpecParsing.parseSortSpec(indexSortStr, core.getLatestSchema()).getSort(); + indexOrMergeSort = indexSort; + } else { + indexSort = null; + indexOrMergeSort = mergeSort; + } + } if (cmdSort == null || cmdLen <= 0 - || mergeSort == null - || !EarlyTerminatingSortingCollector.canEarlyTerminate(cmdSort, mergeSort)) { + || indexOrMergeSort == null + || !EarlyTerminatingSortingCollector.canEarlyTerminate(cmdSort, indexOrMergeSort)) { log.warn( - "unsupported combination: segmentTerminateEarly=true cmdSort={} cmdLen={} mergeSort={}", + "unsupported combination: segmentTerminateEarly=true cmdSort={} cmdLen={} indexOrMergeSort={}", cmdSort, cmdLen, - mergeSort); + indexOrMergeSort); } else { collector = earlyTerminatingSortingCollector = 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..cf4c8520f1c 100644 --- a/solr/core/src/java/org/apache/solr/update/SolrIndexConfig.java +++ b/solr/core/src/java/org/apache/solr/update/SolrIndexConfig.java @@ -44,6 +44,8 @@ import org.apache.solr.index.MergePolicyFactoryArgs; import org.apache.solr.index.SortingMergePolicy; import org.apache.solr.schema.IndexSchema; +import org.apache.solr.search.SortSpec; +import org.apache.solr.search.SortSpecParsing; import org.apache.solr.util.SolrPluginUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -85,6 +87,7 @@ public class SolrIndexConfig implements MapSerializable { public final int writeLockTimeout; public final String lockType; + public final String indexSort; public final PluginInfo mergePolicyFactoryInfo; public final PluginInfo mergeSchedulerInfo; public final PluginInfo metricsInfo; @@ -103,6 +106,7 @@ private SolrIndexConfig() { maxCommitMergeWaitMillis = -1; writeLockTimeout = -1; lockType = DirectoryFactory.LOCK_TYPE_NATIVE; + indexSort = null; mergePolicyFactoryInfo = null; mergeSchedulerInfo = null; mergedSegmentWarmerInfo = null; @@ -158,6 +162,7 @@ public SolrIndexConfig(ConfigNode cfg, SolrIndexConfig def) { writeLockTimeout = get("writeLockTimeout").intVal(def.writeLockTimeout); lockType = get("lockType").txt(def.lockType); + indexSort = get("indexSort").txt(def.indexSort); metricsInfo = getPluginInfo(get("metrics"), def.metricsInfo); mergeSchedulerInfo = getPluginInfo(get("mergeScheduler"), def.mergeSchedulerInfo); @@ -214,6 +219,9 @@ public Map toMap(Map map) { if (metricsInfo != null) { map.put("metrics", metricsInfo); } + if (indexSort != null) { + map.put("indexSort", indexSort); + } if (mergePolicyFactoryInfo != null) { map.put("mergePolicyFactory", mergePolicyFactoryInfo); } @@ -265,9 +273,20 @@ public IndexWriterConfig toIndexWriterConfig(SolrCore core) throws IOException { iwc.setMergeScheduler(mergeScheduler); iwc.setInfoStream(infoStream); + if (indexSort != null) { + SortSpec indexSortSpec = SortSpecParsing.parseSortSpec(indexSort, schema); + iwc.setIndexSort(indexSortSpec.getSort()); + } + if (mergePolicy instanceof SortingMergePolicy) { - Sort indexSort = ((SortingMergePolicy) mergePolicy).getSort(); - iwc.setIndexSort(indexSort); + Sort mergeSort = ((SortingMergePolicy) mergePolicy).getSort(); + Sort indexSort = iwc.getIndexSort(); + if (indexSort != null && !indexSort.equals(mergeSort)) { + log.warn( + "indexSort={} differs from mergePolicySort={} (using indexSort)", indexSort, mergeSort); + } else { + iwc.setIndexSort(mergeSort); + } } iwc.setUseCompoundFile(useCompoundFile); diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-indexSort.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-indexSort.xml new file mode 100644 index 00000000000..0c7c5027b7b --- /dev/null +++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-indexSort.xml @@ -0,0 +1,52 @@ + + + + + + ${tests.luceneMatchVersion:LATEST} + + + + + ${solr.tests.lockType:single} + timestamp_i_dvo desc + + + + + + + ${solr.ulog.dir:} + + + + ${solr.autoCommit.maxTime:-1} + false + + + + ${solr.autoSoftCommit.maxTime:-1} + + + + + text + + + + diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-sortingmergepolicyfactory.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-sortingmergepolicyfactory.xml index 5920348551a..092747de1b0 100644 --- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-sortingmergepolicyfactory.xml +++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-sortingmergepolicyfactory.xml @@ -29,6 +29,7 @@ ${mergePolicySort:timestamp_i_dvo desc} ${solr.tests.lockType:single} + timestamp_i_dvo desc 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..4459d34b67a 100644 --- a/solr/core/src/test/org/apache/solr/cloud/TestSegmentSorting.java +++ b/solr/core/src/test/org/apache/solr/cloud/TestSegmentSorting.java @@ -71,9 +71,13 @@ public void createCollection() throws Exception { collectionName = testName.getMethodName(); final CloudSolrClient cloudSolrClient = cluster.getSolrClient(); + final String solrConfigFileName = + random().nextBoolean() + ? "solrconfig-sortingmergepolicyfactory.xml" + : "solrconfig-indexSort.xml"; + final Map collectionProperties = new HashMap<>(); - collectionProperties.put( - CoreDescriptor.CORE_CONFIG, "solrconfig-sortingmergepolicyfactory.xml"); + collectionProperties.put(CoreDescriptor.CORE_CONFIG, solrConfigFileName); CollectionAdminRequest.Create cmd = CollectionAdminRequest.createCollection( 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 2a59bbb8312..b6a227da467 100644 --- a/solr/core/src/test/org/apache/solr/update/SolrIndexConfigTest.java +++ b/solr/core/src/test/org/apache/solr/update/SolrIndexConfigTest.java @@ -55,6 +55,7 @@ public class SolrIndexConfigTest extends SolrTestCaseJ4 { "solrconfig-concurrentmergescheduler.xml"; private static final String solrConfigFileNameSortingMergePolicyFactory = "solrconfig-sortingmergepolicyfactory.xml"; + private static final String solrConfigFileNameIndexSort = "solrconfig-indexSort.xml"; private static final String schemaFileName = "schema.xml"; private static boolean compoundMergePolicySort = false; @@ -116,6 +117,8 @@ public void testTieredMPSolrIndexConfigCreation() throws Exception { assertEquals("ms.maxMergeCount", 987, ms.getMaxMergeCount()); assertEquals("ms.maxThreadCount", 42, ms.getMaxThreadCount()); assertTrue("ms.isAutoIOThrottle", ms.getAutoIOThrottle()); + + assertNull("indexSort", iwc.getIndexSort()); } @Test @@ -137,6 +140,8 @@ public void testConcurrentMergeSchedularSolrIndexConfigCreation() throws Excepti assertEquals("ms.maxMergeCount", 987, ms.getMaxMergeCount()); assertEquals("ms.maxThreadCount", 42, ms.getMaxThreadCount()); assertFalse("ms.isAutoIOThrottle", ms.getAutoIOThrottle()); + + assertNull("indexSort", iwc.getIndexSort()); } public void testSortingMPSolrIndexConfigCreation() throws Exception { @@ -167,6 +172,25 @@ public void testSortingMPSolrIndexConfigCreation() throws Exception { } final Sort actual = sortingMergePolicy.getSort(); assertEquals("SortingMergePolicy.getSort", expected, actual); + assertEquals("indexSort", expected, iwc.getIndexSort()); + } + + public void testIndexSortSolrIndexConfigCreation() throws Exception { + final String expectedFieldName = "timestamp_i_dvo"; + final SortField.Type expectedFieldType = SortField.Type.INT; + final boolean expectedFieldSortDescending = true; + + SolrConfig solrConfig = new SolrConfig(instanceDir, solrConfigFileNameIndexSort); + SolrIndexConfig solrIndexConfig = new SolrIndexConfig(solrConfig, null); + assertNotNull(solrIndexConfig); + IndexSchema indexSchema = IndexSchemaFactory.buildIndexSchema(schemaFileName, solrConfig); + + h.getCore().setLatestSchema(indexSchema); + IndexWriterConfig iwc = solrIndexConfig.toIndexWriterConfig(h.getCore()); + + final Sort expected = + new Sort(new SortField(expectedFieldName, expectedFieldType, expectedFieldSortDescending)); + assertEquals("indexSort", expected, iwc.getIndexSort()); } public void testMergedSegmentWarmerIndexConfigCreation() throws Exception { @@ -182,6 +206,8 @@ public void testMergedSegmentWarmerIndexConfigCreation() throws Exception { h.getCore().setLatestSchema(indexSchema); IndexWriterConfig iwc = solrIndexConfig.toIndexWriterConfig(h.getCore()); assertEquals(SimpleMergedSegmentWarmer.class, iwc.getMergedSegmentWarmer().getClass()); + + assertNull("indexSort", iwc.getIndexSort()); } public void testToMap() throws Exception {