You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by md...@apache.org on 2021/07/15 19:43:02 UTC

[solr] branch main updated: SOLR-15531: significantTerms streaming function should not fail on empty collections (#212)

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

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


The following commit(s) were added to refs/heads/main by this push:
     new 5346024  SOLR-15531: significantTerms streaming function should not fail on empty collections (#212)
5346024 is described below

commit 5346024eefc7139de215ea24ccc551d624280144
Author: Benedikt Arnold <be...@benarnold.de>
AuthorDate: Thu Jul 15 21:42:52 2021 +0200

    SOLR-15531: significantTerms streaming function should not fail on empty collections (#212)
---
 solr/CHANGES.txt                                   |   2 +
 .../solr/search/SignificantTermsQParserPlugin.java |  33 +++++
 .../search/SignificantTermsQParserPluginTest.java  | 135 +++++++++++++++++++--
 3 files changed, 160 insertions(+), 10 deletions(-)

diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 6fcd5da..e9cdb6f 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -383,6 +383,8 @@ Bug Fixes
 * SOLR-15311: Support async parameter in MODIFYCOLLECTION
   (Nazerke Seidan, Christine Poerschke, David Smiley)
 
+* SOLR-15531: SignificantTerms streaming function should not fail on empty collections (Benedikt Arnold via Mike Drob)
+
 Other Changes
 ---------------------
 (No changes)
diff --git a/solr/core/src/java/org/apache/solr/search/SignificantTermsQParserPlugin.java b/solr/core/src/java/org/apache/solr/search/SignificantTermsQParserPlugin.java
index 7415e67..1aea7a4 100644
--- a/solr/core/src/java/org/apache/solr/search/SignificantTermsQParserPlugin.java
+++ b/solr/core/src/java/org/apache/solr/search/SignificantTermsQParserPlugin.java
@@ -89,10 +89,43 @@ public class SignificantTermsQParserPlugin extends QParserPlugin {
 
     @Override
     public DelegatingCollector getAnalyticsCollector(ResponseBuilder rb, IndexSearcher searcher) {
+      if (searcher.getIndexReader().maxDoc() <= 0) {
+        return new NoOpTermsCollector(rb);
+      }
       return new SignifcantTermsCollector(rb, searcher, field, numTerms, minDocs, maxDocs, minTermLength);
     }
   }
 
+  private static class NoOpTermsCollector extends DelegatingCollector {
+    private ResponseBuilder rb;
+
+    private NoOpTermsCollector(ResponseBuilder rb) {
+      this.rb = rb;
+    }
+
+    @Override
+    public void collect(int doc) throws IOException {
+    }
+
+    @Override
+    public void finish() throws IOException {
+      List<String> outTerms = new ArrayList<>();
+      List<Integer> outFreq = new ArrayList<>();
+      List<Integer> outQueryFreq = new ArrayList<>();
+      List<Double> scores = new ArrayList<>();
+
+      LinkedHashMap<String, Object> response = new LinkedHashMap<>();
+
+      rb.rsp.add(NAME, response);
+
+      response.put("numDocs", 0);
+      response.put("sterms", outTerms);
+      response.put("scores", scores);
+      response.put("docFreq", outFreq);
+      response.put("queryDocFreq", outQueryFreq);
+    }
+  }
+
   private static class SignifcantTermsCollector extends DelegatingCollector {
 
     private String field;
diff --git a/solr/core/src/test/org/apache/solr/search/SignificantTermsQParserPluginTest.java b/solr/core/src/test/org/apache/solr/search/SignificantTermsQParserPluginTest.java
index bcd66da..b8cdd01 100644
--- a/solr/core/src/test/org/apache/solr/search/SignificantTermsQParserPluginTest.java
+++ b/solr/core/src/test/org/apache/solr/search/SignificantTermsQParserPluginTest.java
@@ -17,19 +17,134 @@
 
 package org.apache.solr.search;
 
+import org.apache.commons.io.FileUtils;
 import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.common.SolrInputDocument;
+import org.apache.solr.common.params.MapSolrParams;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.handler.component.ResponseBuilder;
+import org.apache.solr.request.LocalSolrQueryRequest;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.update.AddUpdateCommand;
+import org.apache.solr.update.CommitUpdateCommand;
+import org.apache.solr.update.DeleteUpdateCommand;
+import org.apache.solr.util.RefCounted;
+import org.junit.BeforeClass;
 import org.junit.Test;
 
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
 public class SignificantTermsQParserPluginTest extends SolrTestCaseJ4 {
 
-  /**
-   * Test the backwards compatibility for a typo in the SignificantTermsQParserPlugin. It will fail if the backwards
-   * compatibility is broken.
-   */
-  @Test
-  public void testQParserBackwardsCompatibility() {
-    assertEquals("significantTerms", SignificantTermsQParserPlugin.NAME);
-    assertEquals(SignificantTermsQParserPlugin.class,
-        QParserPlugin.standardPlugins.get(SignificantTermsQParserPlugin.NAME).getClass());
-  }
+    @BeforeClass
+    public static void setUpCore() throws Exception {
+        String tmpSolrHome = createTempDir().toFile().getAbsolutePath();
+        FileUtils.copyDirectory(new File(TEST_HOME()), new File(tmpSolrHome).getAbsoluteFile());
+        initCore("solrconfig.xml", "schema.xml", new File(tmpSolrHome).getAbsolutePath());
+    }
+
+    /**
+     * Test the backwards compatibility for a typo in the SignificantTermsQParserPlugin. It will fail if the backwards
+     * compatibility is broken.
+     */
+    @Test
+    public void testQParserBackwardsCompatibility() {
+        assertEquals("significantTerms", SignificantTermsQParserPlugin.NAME);
+        assertEquals(SignificantTermsQParserPlugin.class,
+                QParserPlugin.standardPlugins.get(SignificantTermsQParserPlugin.NAME).getClass());
+    }
+
+    @Test
+    public void testEmptyCollectionDoesNotThrow() throws Exception {
+        SolrCore emptyCore = h.getCore();
+        QParserPlugin qParserPlugin = QParserPlugin.standardPlugins.get(SignificantTermsQParserPlugin.NAME);
+        Map<String, String> params = new HashMap<>();
+        params.put("field", "cat");
+        QParser parser = qParserPlugin.createParser("", new MapSolrParams(params), new MapSolrParams(new HashMap<>()), null);
+        AnalyticsQuery query = (AnalyticsQuery) parser.parse();
+        SolrQueryResponse resp = new SolrQueryResponse();
+
+        RefCounted<SolrIndexSearcher> searcher = emptyCore.getSearcher();
+        try {
+            DelegatingCollector analyticsCollector = query.getAnalyticsCollector(new ResponseBuilder(null, resp, Collections.emptyList()), searcher.get());
+            assertNotNull(analyticsCollector);
+            analyticsCollector.finish();
+            LinkedHashMap<String, Object> expectedValues = new LinkedHashMap<>();
+            expectedValues.put("numDocs", 0);
+            expectedValues.put("sterms", new ArrayList<String>());
+            expectedValues.put("scores", new ArrayList<Integer>());
+            expectedValues.put("docFreq", new ArrayList<Integer>());
+            expectedValues.put("queryDocFreq", new ArrayList<Double>());
+            assertEquals(expectedValues, resp.getValues().get("significantTerms"));
+        } finally {
+            searcher.decref();
+        }
+
+    }
+
+    @Test
+    public void testCollectionWithDocuments() throws Exception {
+        SolrCore dataCore = h.getCore();
+        addTestDocs(dataCore);
+
+        QParserPlugin qParserPlugin = QParserPlugin.standardPlugins.get(SignificantTermsQParserPlugin.NAME);
+        Map<String, String> params = new HashMap<>();
+        params.put("field", "cat");
+        QParser parser = qParserPlugin.createParser("", new MapSolrParams(params), new MapSolrParams(new HashMap<>()), null);
+        AnalyticsQuery query = (AnalyticsQuery) parser.parse();
+        SolrQueryResponse resp = new SolrQueryResponse();
+
+        ResponseBuilder responseBuilder = new ResponseBuilder(null, resp, Collections.emptyList());
+        RefCounted<SolrIndexSearcher> searcher = dataCore.getSearcher();
+        try {
+
+            DelegatingCollector analyticsCollector = query.getAnalyticsCollector(responseBuilder, searcher.get());
+            assertNotNull(analyticsCollector);
+            analyticsCollector.finish();
+
+            LinkedHashMap<String, Object> expectedValues = new LinkedHashMap<>();
+            expectedValues.put("numDocs", 1);
+            expectedValues.put("sterms", new ArrayList<String>());
+            expectedValues.put("scores", new ArrayList<Integer>());
+            expectedValues.put("docFreq", new ArrayList<Integer>());
+            expectedValues.put("queryDocFreq", new ArrayList<Double>());
+
+            assertEquals(expectedValues, resp.getValues().get("significantTerms"));
+
+        } finally {
+            searcher.decref();
+        }
+
+        deleteTestDocs(dataCore);
+    }
+
+    private void addTestDocs(SolrCore core) throws IOException {
+        SolrQueryRequest coreReq = new LocalSolrQueryRequest(core, new ModifiableSolrParams());
+        AddUpdateCommand cmd = new AddUpdateCommand(coreReq);
+        cmd.solrDoc = new SolrInputDocument();
+        cmd.solrDoc.addField("id", "1");
+        cmd.solrDoc.addField("cat", "foo");
+        core.getUpdateHandler().addDoc(cmd);
+
+        core.getUpdateHandler().commit(new CommitUpdateCommand(coreReq, true));
+        coreReq.close();
+    }
+
+    private void deleteTestDocs(SolrCore core) throws IOException {
+        SolrQueryRequest coreReq = new LocalSolrQueryRequest(core, new ModifiableSolrParams());
+        DeleteUpdateCommand cmd = new DeleteUpdateCommand(coreReq);
+        cmd.id = "1";
+        core.getUpdateHandler().delete(cmd);
+        core.getUpdateHandler().commit(new CommitUpdateCommand(coreReq, true));
+        coreReq.close();
+    }
+
 }