You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by tf...@apache.org on 2014/08/08 03:25:05 UTC

svn commit: r1616656 - in /lucene/dev/branches/branch_4x: ./ solr/ solr/core/ solr/core/src/test/org/apache/solr/ solr/solrj/ solr/solrj/src/java/org/apache/solr/client/solrj/ solr/solrj/src/java/org/apache/solr/client/solrj/response/ solr/solrj/src/te...

Author: tflobbe
Date: Fri Aug  8 01:25:04 2014
New Revision: 1616656

URL: http://svn.apache.org/r1616656
Log:
SOLR-6283: Add support for Interval Faceting in SolrJ

Added:
    lucene/dev/branches/branch_4x/solr/solrj/src/java/org/apache/solr/client/solrj/response/IntervalFacet.java
      - copied unchanged from r1616628, lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/client/solrj/response/IntervalFacet.java
    lucene/dev/branches/branch_4x/solr/solrj/src/test-files/solrj/sampleIntervalFacetsResponse.xml
      - copied unchanged from r1616628, lucene/dev/trunk/solr/solrj/src/test-files/solrj/sampleIntervalFacetsResponse.xml
Modified:
    lucene/dev/branches/branch_4x/   (props changed)
    lucene/dev/branches/branch_4x/solr/   (props changed)
    lucene/dev/branches/branch_4x/solr/CHANGES.txt   (contents, props changed)
    lucene/dev/branches/branch_4x/solr/core/   (props changed)
    lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/DistributedIntervalFacetingTest.java
    lucene/dev/branches/branch_4x/solr/solrj/   (props changed)
    lucene/dev/branches/branch_4x/solr/solrj/src/java/org/apache/solr/client/solrj/SolrQuery.java
    lucene/dev/branches/branch_4x/solr/solrj/src/java/org/apache/solr/client/solrj/response/QueryResponse.java
    lucene/dev/branches/branch_4x/solr/solrj/src/test/org/apache/solr/client/solrj/SolrQueryTest.java
    lucene/dev/branches/branch_4x/solr/solrj/src/test/org/apache/solr/client/solrj/response/QueryResponseTest.java

Modified: lucene/dev/branches/branch_4x/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/CHANGES.txt?rev=1616656&r1=1616655&r2=1616656&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/solr/CHANGES.txt (original)
+++ lucene/dev/branches/branch_4x/solr/CHANGES.txt Fri Aug  8 01:25:04 2014
@@ -106,6 +106,7 @@ New Features
 * SOLR-6318: New "terms" QParser for efficiently filtering documents by a list of values. For
   many values, it's more appropriate than a boolean query. (David Smiley)
 
+* SOLR-6283: Add support for Interval Faceting in SolrJ. (Tomás Fernández Löbbe)
 
 Bug Fixes
 ----------------------

Modified: lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/DistributedIntervalFacetingTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/DistributedIntervalFacetingTest.java?rev=1616656&r1=1616655&r2=1616656&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/DistributedIntervalFacetingTest.java (original)
+++ lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/DistributedIntervalFacetingTest.java Fri Aug  8 01:25:04 2014
@@ -2,9 +2,13 @@ package org.apache.solr;
 
 import java.util.Arrays;
 import java.util.Comparator;
+import java.util.List;
 
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.LuceneTestCase.Slow;
+import org.apache.solr.client.solrj.SolrQuery;
+import org.apache.solr.client.solrj.response.IntervalFacet.Count;
+import org.apache.solr.client.solrj.response.QueryResponse;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.junit.BeforeClass;
 
@@ -40,6 +44,61 @@ public class DistributedIntervalFaceting
     del("*:*");
     commit();
     testRandom();
+    del("*:*");
+    commit();
+    testSolrJ();
+  }
+
+  private void testSolrJ() throws Exception {
+    indexr("id", "0", "test_i_dv", "0", "test_s_dv", "AAA");
+    indexr("id", "1", "test_i_dv", "1", "test_s_dv", "BBB");
+    indexr("id", "2", "test_i_dv", "2", "test_s_dv", "AAA");
+    indexr("id", "3", "test_i_dv", "3", "test_s_dv", "CCC");
+    commit();
+    
+    QueryResponse response = controlClient.query(new SolrQuery("*:*"));
+    assertEquals(4, response.getResults().getNumFound());
+    
+    SolrQuery q = new SolrQuery("*:*");
+    String[] intervals =  new String[]{"[0,1)","[1,2)", "[2,3)", "[3,*)"};
+    q.addIntervalFacets("test_i_dv", intervals);
+    response = controlClient.query(q);
+    assertEquals(1, response.getIntervalFacets().size());
+    assertEquals("test_i_dv", response.getIntervalFacets().get(0).getField());
+    assertEquals(4, response.getIntervalFacets().get(0).getIntervals().size());
+    for (int i = 0; i < response.getIntervalFacets().get(0).getIntervals().size(); i++) {
+      Count count = response.getIntervalFacets().get(0).getIntervals().get(i);
+      assertEquals(intervals[i], count.getKey());
+      assertEquals(1, count.getCount());
+    }
+    
+    q = new SolrQuery("*:*");
+    q.addIntervalFacets("test_i_dv", intervals);
+    q.addIntervalFacets("test_s_dv", new String[]{"{!key='AAA'}[AAA,AAA]", "{!key='BBB'}[BBB,BBB]", "{!key='CCC'}[CCC,CCC]"});
+    response = controlClient.query(q);
+    assertEquals(2, response.getIntervalFacets().size());
+    
+    int stringIntervalIndex = "test_s_dv".equals(response.getIntervalFacets().get(0).getField())?0:1;
+        
+    assertEquals("test_i_dv", response.getIntervalFacets().get(1-stringIntervalIndex).getField());
+    assertEquals("test_s_dv", response.getIntervalFacets().get(stringIntervalIndex).getField());
+    
+    for (int i = 0; i < response.getIntervalFacets().get(1-stringIntervalIndex).getIntervals().size(); i++) {
+      Count count = response.getIntervalFacets().get(1-stringIntervalIndex).getIntervals().get(i);
+      assertEquals(intervals[i], count.getKey());
+      assertEquals(1, count.getCount());
+    }
+    
+    List<Count> stringIntervals = response.getIntervalFacets().get(stringIntervalIndex).getIntervals();
+    assertEquals(3, stringIntervals.size());
+    assertEquals("AAA", stringIntervals.get(0).getKey());
+    assertEquals(2, stringIntervals.get(0).getCount());
+    
+    assertEquals("BBB", stringIntervals.get(1).getKey());
+    assertEquals(1, stringIntervals.get(1).getCount());
+    
+    assertEquals("CCC", stringIntervals.get(2).getKey());
+    assertEquals(1, stringIntervals.get(2).getCount());
   }
 
   private void testRandom() throws Exception {

Modified: lucene/dev/branches/branch_4x/solr/solrj/src/java/org/apache/solr/client/solrj/SolrQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/solrj/src/java/org/apache/solr/client/solrj/SolrQuery.java?rev=1616656&r1=1616655&r2=1616656&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/solr/solrj/src/java/org/apache/solr/client/solrj/SolrQuery.java (original)
+++ lucene/dev/branches/branch_4x/solr/solrj/src/java/org/apache/solr/client/solrj/SolrQuery.java Fri Aug  8 01:25:04 2014
@@ -17,6 +17,13 @@
 
 package org.apache.solr.client.solrj;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.regex.Pattern;
+
 import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.common.params.FacetParams;
 import org.apache.solr.common.params.HighlightParams;
@@ -25,13 +32,6 @@ import org.apache.solr.common.params.Sta
 import org.apache.solr.common.params.TermsParams;
 import org.apache.solr.common.util.DateUtil;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-import java.util.regex.Pattern;
-
 
 /**
  * This is an augmented SolrParams with get/set/add fields for common fields used
@@ -273,7 +273,40 @@ public class SolrQuery extends Modifiabl
     this.set(FacetParams.FACET, true);
     return this;
   }
-
+  
+  /**
+   * Add Interval Faceting on a field. All intervals for the same field should be included
+   * in the same call to this method.
+   * For syntax documentation see <a href="https://wiki.apache.org/solr/SimpleFacetParameters#Interval_Faceting">Solr wiki</a>
+   * 
+   * @param field the field to add facet intervals
+   * @param intervals Intervals to be used for faceting. It can be an empty array, but it can't 
+   * be <code>null</code>
+   * @return this
+   */
+  public SolrQuery addIntervalFacets(String field, String[] intervals) {
+    if (intervals == null) {
+      throw new IllegalArgumentException("Can't add null intervals");
+    }
+    set(FacetParams.FACET, true);
+    add(FacetParams.FACET_INTERVAL, field);
+    for (String interval:intervals) {
+      add(String.format(Locale.ROOT, "f.%s.facet.interval.set", field), interval);
+    }
+    return this;
+  }
+  
+  /**
+   * Remove all Interval Facets on a field
+   * 
+   * @param field the field to remove from facet intervals
+   * @return Array of current intervals for <code>field</code>
+   */
+  public String[] removeIntervalFacets(String field) {
+    while(remove(FacetParams.FACET_INTERVAL, field)){};
+    return remove(String.format(Locale.ROOT, "f.%s.facet.interval.set", field));
+  }
+  
   /** get the facet fields
    * 
    * @return string array of facet fields or null if not set/empty
@@ -317,6 +350,7 @@ public class SolrQuery extends Modifiabl
       this.remove(FacetParams.FACET_SORT);
       this.remove(FacetParams.FACET_ZEROS);
       this.remove(FacetParams.FACET_PREFIX); // does not include the individual fields...
+      this.remove(FacetParams.FACET_INTERVAL); // does not remove interval parameters
     }
     return this;
   }

Modified: lucene/dev/branches/branch_4x/solr/solrj/src/java/org/apache/solr/client/solrj/response/QueryResponse.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/solrj/src/java/org/apache/solr/client/solrj/response/QueryResponse.java?rev=1616656&r1=1616655&r2=1616656&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/solr/solrj/src/java/org/apache/solr/client/solrj/response/QueryResponse.java (original)
+++ lucene/dev/branches/branch_4x/solr/solrj/src/java/org/apache/solr/client/solrj/response/QueryResponse.java Fri Aug  8 01:25:04 2014
@@ -17,14 +17,19 @@
 
 package org.apache.solr.client.solrj.response;
 
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
 import org.apache.solr.client.solrj.SolrServer;
 import org.apache.solr.client.solrj.beans.DocumentObjectBinder;
 import org.apache.solr.common.SolrDocumentList;
+import org.apache.solr.common.params.CursorMarkParams;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.util.SimpleOrderedMap;
-import org.apache.solr.common.params.CursorMarkParams;
-
-import java.util.*;
 
 /**
  * 
@@ -60,6 +65,7 @@ public class QueryResponse extends SolrR
   private List<FacetField> _facetDates = null;
   private List<RangeFacet> _facetRanges = null;
   private NamedList<List<PivotField>> _facetPivot = null;
+  private List<IntervalFacet> _intervalFacets = null;
 
   // Highlight Info
   private Map<String,Map<String,List<String>>> _highlighting = null;
@@ -363,6 +369,20 @@ public class QueryResponse extends SolrR
         _facetPivot.add( pf.getName(i), readPivots( (List<NamedList>)pf.getVal(i) ) );
       }
     }
+    
+    //Parse interval facets
+    NamedList<NamedList<Object>> intervalsNL = (NamedList<NamedList<Object>>) info.get("facet_intervals");
+    if (intervalsNL != null) {
+      _intervalFacets = new ArrayList<>(intervalsNL.size());
+      for (Map.Entry<String, NamedList<Object>> intervalField : intervalsNL) {
+        String field = intervalField.getKey();
+        List<IntervalFacet.Count> counts = new ArrayList<IntervalFacet.Count>(intervalField.getValue().size());
+        for (Map.Entry<String, Object> interval : intervalField.getValue()) {
+          counts.add(new IntervalFacet.Count(interval.getKey(), (Integer)interval.getValue()));
+        }
+        _intervalFacets.add(new IntervalFacet(field, counts));
+      }
+    }
   }
   
   protected List<PivotField> readPivots( List<NamedList> list )
@@ -466,6 +486,10 @@ public class QueryResponse extends SolrR
     return _facetPivot;
   }
   
+  public List<IntervalFacet> getIntervalFacets() {
+    return _intervalFacets;
+  }
+  
   /** get
    * 
    * @param name the name of the

Modified: lucene/dev/branches/branch_4x/solr/solrj/src/test/org/apache/solr/client/solrj/SolrQueryTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/solrj/src/test/org/apache/solr/client/solrj/SolrQueryTest.java?rev=1616656&r1=1616655&r2=1616656&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/solr/solrj/src/test/org/apache/solr/client/solrj/SolrQueryTest.java (original)
+++ lucene/dev/branches/branch_4x/solr/solrj/src/test/org/apache/solr/client/solrj/SolrQueryTest.java Fri Aug  8 01:25:04 2014
@@ -417,4 +417,36 @@ public class SolrQueryTest extends Lucen
     solrQuery.addFacetQuery("field:value");
     assertTrue("Adding a Facet Query should enable facets", solrQuery.getBool(FacetParams.FACET));
   }
+  
+  public void testFacetInterval() {
+    SolrQuery solrQuery = new SolrQuery();
+    solrQuery.addIntervalFacets("field1", new String[]{});
+    assertTrue(solrQuery.getBool(FacetParams.FACET));
+    assertEquals("field1", solrQuery.get(FacetParams.FACET_INTERVAL));
+    
+    solrQuery.addIntervalFacets("field2", new String[]{"[1,10]"});
+    assertArrayEquals(new String[]{"field1", "field2"}, solrQuery.getParams(FacetParams.FACET_INTERVAL));
+    assertEquals("[1,10]", solrQuery.get("f.field2.facet.interval.set"));
+    
+    solrQuery.addIntervalFacets("field3", new String[]{"[1,10]", "(10,100]", "(100,1000]", "(1000,*]"});
+    assertArrayEquals(new String[]{"field1", "field2", "field3"}, solrQuery.getParams(FacetParams.FACET_INTERVAL));
+    assertArrayEquals(new String[]{"[1,10]", "(10,100]", "(100,1000]", "(1000,*]"}, solrQuery.getParams("f.field3.facet.interval.set"));
+    
+    //Validate adding more intervals for an existing field
+    solrQuery.addIntervalFacets("field2", new String[]{"[10,100]"});
+    assertArrayEquals(new String[]{"[1,10]", "[10,100]"}, solrQuery.getParams("f.field2.facet.interval.set"));
+    
+    assertNull(solrQuery.removeIntervalFacets("field1"));
+    assertArrayEquals(new String[]{"field2", "field3", "field2"}, solrQuery.getParams(FacetParams.FACET_INTERVAL));
+    assertNull(solrQuery.getParams("f.field1.facet.interval.set"));
+    
+    assertArrayEquals(new String[]{"[1,10]", "[10,100]"}, solrQuery.removeIntervalFacets("field2"));
+    assertArrayEquals(new String[]{"field3"}, solrQuery.getParams(FacetParams.FACET_INTERVAL));
+    assertNull(solrQuery.getParams("f.field2.facet.interval.set"));
+    
+    assertArrayEquals(new String[]{"[1,10]", "(10,100]", "(100,1000]", "(1000,*]"}, solrQuery.removeIntervalFacets("field3"));
+    assertNull(solrQuery.getParams(FacetParams.FACET_INTERVAL));
+    assertNull(solrQuery.getParams("f.field3.facet.interval.set"));
+    
+  }
 }

Modified: lucene/dev/branches/branch_4x/solr/solrj/src/test/org/apache/solr/client/solrj/response/QueryResponseTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/solrj/src/test/org/apache/solr/client/solrj/response/QueryResponseTest.java?rev=1616656&r1=1616655&r2=1616656&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/solr/solrj/src/test/org/apache/solr/client/solrj/response/QueryResponseTest.java (original)
+++ lucene/dev/branches/branch_4x/solr/solrj/src/test/org/apache/solr/client/solrj/response/QueryResponseTest.java Fri Aug  8 01:25:04 2014
@@ -262,5 +262,49 @@ public class QueryResponseTest extends L
     assertEquals("708_AR", documents.get(8).getFieldValue("acco_id"));
     assertEquals("708_HI", documents.get(9).getFieldValue("acco_id"));
   }
+  
+  
+  public void testIntervalFacetsResponse() throws Exception {
+    XMLResponseParser parser = new XMLResponseParser();
+    try(SolrResourceLoader loader = new SolrResourceLoader(null, null)) {
+      InputStream is = loader.openResource("solrj/sampleIntervalFacetsResponse.xml");
+      assertNotNull(is);
+      Reader in = new InputStreamReader(is, StandardCharsets.UTF_8);
+      NamedList<Object> response = parser.processResponse(in);
+      in.close();
+      
+      QueryResponse qr = new QueryResponse(response, null);
+      assertNotNull(qr);
+      assertNotNull(qr.getIntervalFacets());
+      assertEquals(2, qr.getIntervalFacets().size());
+      
+      IntervalFacet facet = qr.getIntervalFacets().get(0);
+      assertEquals("price", facet.getField());
+      assertEquals(3, facet.getIntervals().size());
+      
+      assertEquals("[0,10]", facet.getIntervals().get(0).getKey());
+      assertEquals("(10,100]", facet.getIntervals().get(1).getKey());
+      assertEquals("(100,*]", facet.getIntervals().get(2).getKey());
+      
+      assertEquals(3, facet.getIntervals().get(0).getCount());
+      assertEquals(4, facet.getIntervals().get(1).getCount());
+      assertEquals(9, facet.getIntervals().get(2).getCount());
+      
+      
+      facet = qr.getIntervalFacets().get(1);
+      assertEquals("popularity", facet.getField());
+      assertEquals(3, facet.getIntervals().size());
+      
+      assertEquals("bad", facet.getIntervals().get(0).getKey());
+      assertEquals("average", facet.getIntervals().get(1).getKey());
+      assertEquals("good", facet.getIntervals().get(2).getKey());
+      
+      assertEquals(3, facet.getIntervals().get(0).getCount());
+      assertEquals(10, facet.getIntervals().get(1).getCount());
+      assertEquals(2, facet.getIntervals().get(2).getCount());
+      
+    }
+    
+  }
 
 }