diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index e6316b30910..46461d0356d 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -342,9 +342,12 @@ New Features * SOLR-2523: Added support in SolrJ to easily interact with range facets. The range facet response can be parsed and is retrievable from the - QueryResponse class. The SolrQuery has convenient methods for using + QueryResponse class. The SolrQuery class has convenient methods for using range facets. (Martijn van Groningen) +* SOLR-2637: Added support for group result parsing in SolrJ. + (Tao Cheng, Martijn van Groningen) + Optimizations ---------------------- diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/XMLResponseParser.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/XMLResponseParser.java index d17b3e647fe..27c01a1c995 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/XMLResponseParser.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/XMLResponseParser.java @@ -17,23 +17,7 @@ package org.apache.solr.client.solrj.impl; -import java.io.Reader; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Locale; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamConstants; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamReader; - import org.apache.solr.client.solrj.ResponseParser; -import org.apache.solr.client.solrj.util.ClientUtils; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.SolrException; @@ -41,6 +25,19 @@ import org.apache.solr.common.util.DateUtil; import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.SimpleOrderedMap; import org.apache.solr.common.util.XMLErrorLogger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import java.io.InputStream; +import java.io.Reader; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Locale; /** * @@ -306,10 +303,10 @@ public class XMLResponseParser extends ResponseParser if( !type.isLeaf ) { switch( type ) { - case LST: vals.add( readNamedList( parser ) ); continue; - case ARR: vals.add( readArray( parser ) ); continue; - case RESULT: vals.add( readDocuments( parser ) ); continue; - case DOC: vals.add( readDocument( parser ) ); continue; + case LST: vals.add( readNamedList( parser ) ); depth--; continue; + case ARR: vals.add( readArray( parser ) ); depth--; continue; + case RESULT: vals.add( readDocuments( parser ) ); depth--; continue; + case DOC: vals.add( readDocument( parser ) ); depth--; continue; } throw new XMLStreamException( "branch element not handled!", parser.getLocation() ); } diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/response/Group.java b/solr/solrj/src/java/org/apache/solr/client/solrj/response/Group.java new file mode 100644 index 00000000000..2ee0389fbc6 --- /dev/null +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/response/Group.java @@ -0,0 +1,69 @@ +package org.apache.solr.client.solrj.response; + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import org.apache.solr.common.SolrDocumentList; + +import java.io.Serializable; + +/** + * Represents a group. A group contains a common group value that all documents inside the group share and + * documents that belong to this group. + * + * A group value can be a field value, function result or a query string depending on the {@link GroupCommand}. + * In case of a field value or a function result the value is always a indexed value. + * + * @since solr 3.4 + */ +public class Group implements Serializable { + + private final String _groupValue; + private final SolrDocumentList _result; + + /** + * Creates a Group instance. + * + * @param groupValue The common group value (indexed value) that all documents share. + * @param result The documents to be displayed that belong to this group + */ + public Group(String groupValue, SolrDocumentList result) { + _groupValue = groupValue; + _result = result; + } + + /** + * Returns the common group value that all documents share inside this group. + * This is an indexed value, not a stored value. + * + * @return the common group value + */ + public String getGroupValue() { + return _groupValue; + } + + /** + * Returns the documents to be displayed that belong to this group. + * How many documents are returned depend on the group.offset and group.limit parameters. + * + * @return the documents to be displayed that belong to this group + */ + public SolrDocumentList getResult() { + return _result; + } + +} \ No newline at end of file diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/response/GroupCommand.java b/solr/solrj/src/java/org/apache/solr/client/solrj/response/GroupCommand.java new file mode 100644 index 00000000000..80c7726e0da --- /dev/null +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/response/GroupCommand.java @@ -0,0 +1,125 @@ +package org.apache.solr.client.solrj.response; + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * This class represents the result of a group command. + * This can be the result of the following parameter: + * + * + * An instance of this class contains: + * + * + * In case of group.query only one group is present and ngroups is always null. + * + * @since solr 3.4 + */ +public class GroupCommand implements Serializable { + + private final String _name; + private final List _values = new ArrayList(); + private final int _matches; + private final Integer _ngroups; + + /** + * Creates a GroupCommand instance + * + * @param name The name of this command + * @param matches The total number of documents found for this command + */ + public GroupCommand(String name, int matches) { + _name = name; + _matches = matches; + _ngroups = null; + } + + /** + * Creates a GroupCommand instance. + * + * @param name The name of this command + * @param matches The total number of documents found for this command + * @param nGroups The total number of groups found for this command. + */ + public GroupCommand(String name, int matches, int nGroups) { + _name = name; + _matches = matches; + _ngroups = nGroups; + } + + /** + * Returns the name of this command. This can be the field, function or query grouped by. + * + * @return the name of this command + */ + public String getName() { + return _name; + } + + /** + * Adds a group to this command. + * + * @param group A group to be added + */ + public void add(Group group) { + _values.add(group); + } + + /** + * Returns the groups to be displayed. + * The number of groups returned depend on the start and rows parameters. + * + * @return the groups to be displayed. + */ + public List getValues() { + return _values; + } + + /** + * Returns the total number of documents found for this command. + * + * @return the total number of documents found for this command. + */ + public int getMatches() { + return _matches; + } + + /** + * Returns the total number of groups found for this command. + * Returns null if the group.ngroups parameter is unset or false or + * if this is a group command query (parameter = group.query). + * + * @return the total number of groups found for this command. + */ + public Integer getNGroups() { + return _ngroups; + } + +} \ No newline at end of file diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/response/GroupResponse.java b/solr/solrj/src/java/org/apache/solr/client/solrj/response/GroupResponse.java new file mode 100644 index 00000000000..9ec54622252 --- /dev/null +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/response/GroupResponse.java @@ -0,0 +1,56 @@ +package org.apache.solr.client.solrj.response; + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * Overall grouping result. Contains a list of {@link GroupCommand} instances that is the result of + * one the following parameters: + *
    + *
  • group.field + *
  • group.func + *
  • group.query + *
+ * + * @since solr 3.4 + */ +public class GroupResponse implements Serializable { + + private final List _values = new ArrayList(); + + /** + * Adds a grouping command to the response. + * + * @param command The grouping command to add + */ + public void add(GroupCommand command) { + _values.add(command); + } + + /** + * Returns all grouping commands. + * + * @return all grouping commands + */ + public List getValues() { + return _values; + } +} \ No newline at end of file diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/response/QueryResponse.java b/solr/solrj/src/java/org/apache/solr/client/solrj/response/QueryResponse.java index d38d8611a92..8c838751a8a 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/response/QueryResponse.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/response/QueryResponse.java @@ -21,6 +21,7 @@ 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.util.NamedList; +import org.apache.solr.common.util.SimpleOrderedMap; import java.util.*; @@ -43,6 +44,10 @@ public class QueryResponse extends SolrResponseBase private NamedList _statsInfo = null; private NamedList> _termsInfo = null; + // Grouping response + private NamedList _groupedInfo = null; + private GroupResponse _groupResponse = null; + // Facet stuff private Map _facetQuery = null; private List _facetFields = null; @@ -108,7 +113,11 @@ public class QueryResponse extends SolrResponseBase _debugInfo = (NamedList) res.getVal( i ); extractDebugInfo( _debugInfo ); } - else if( "highlighting".equals( n ) ) { + else if( "grouped".equals( n ) ) { + _groupedInfo = (NamedList) res.getVal( i ); + extractGroupedInfo( _groupedInfo ); + } + else if( "highlighting".equals( n ) ) { _highlightingInfo = (NamedList) res.getVal( i ); extractHighlightingInfo( _highlightingInfo ); } @@ -170,6 +179,54 @@ public class QueryResponse extends SolrResponseBase } } + private void extractGroupedInfo( NamedList info ) { + if ( info != null ) { + _groupResponse = new GroupResponse(); + int size = info.size(); + for (int i=0; i < size; i++) { + String fieldName = info.getName(i); + Object fieldGroups = info.getVal(i); + SimpleOrderedMap simpleOrderedMap = (SimpleOrderedMap) fieldGroups; + + Object oMatches = simpleOrderedMap.get("matches"); + Object oNGroups = simpleOrderedMap.get("ngroups"); + Object oGroups = simpleOrderedMap.get("groups"); + Object queryCommand = simpleOrderedMap.get("doclist"); + if (oMatches == null) { + continue; + } + + if (oGroups != null) { + Integer iMatches = (Integer) oMatches; + ArrayList groupsArr = (ArrayList) oGroups; + GroupCommand groupedCommand; + if (oNGroups != null) { + Integer iNGroups = (Integer) oNGroups; + groupedCommand = new GroupCommand(fieldName, iMatches, iNGroups); + } else { + groupedCommand = new GroupCommand(fieldName, iMatches); + } + + for (Object oGrp : groupsArr) { + SimpleOrderedMap grpMap = (SimpleOrderedMap) oGrp; + Object sGroupValue = grpMap.get( "groupValue"); + SolrDocumentList doclist = (SolrDocumentList) grpMap.get( "doclist"); + Group group = new Group(sGroupValue.toString(), doclist) ; + groupedCommand.add(group); + } + + _groupResponse.add(groupedCommand); + } else if (queryCommand != null) { + Integer iMatches = (Integer) oMatches; + GroupCommand groupCommand = new GroupCommand(fieldName, iMatches); + SolrDocumentList docList = (SolrDocumentList) queryCommand; + groupCommand.add(new Group(fieldName, docList)); + _groupResponse.add(groupCommand); + } + } + } + } + private void extractHighlightingInfo( NamedList info ) { _highlighting = new HashMap>>(); @@ -332,6 +389,21 @@ public class QueryResponse extends SolrResponseBase return _facetQuery; } + /** + * Returns the {@link GroupResponse} containing the group commands. + * A group command can be the result of one of the following parameters: + *
    + *
  • group.field + *
  • group.func + *
  • group.query + *
+ * + * @return the {@link GroupResponse} containing the group commands + */ + public GroupResponse getGroupResponse() { + return _groupResponse; + } + public Map>> getHighlighting() { return _highlighting; } @@ -365,7 +437,7 @@ public class QueryResponse extends SolrResponseBase /** get * - * @param name the name of the + * @param name the name of the * @return the FacetField by name or null if it does not exist */ public FacetField getFacetField(String name) { diff --git a/solr/solrj/src/test-files/solrj/sampleGroupResponse.xml b/solr/solrj/src/test-files/solrj/sampleGroupResponse.xml new file mode 100644 index 00000000000..26fcdfa1e8e --- /dev/null +++ b/solr/solrj/src/test-files/solrj/sampleGroupResponse.xml @@ -0,0 +1,384 @@ + + + + 0 + 3451 + + *:* + 2 + acco_id + country:fr + true + + + + + 30000000 + 5687 + + + 116_ar + + + 0 + EG + 116_AR + 417500 + + + 1 + EG + 116_AR + 472500 + + + + + 116_hi + + + 2236 + EG + 116_HI + 475300 + + + 2237 + EG + 116_HI + 475400 + + + + + 953_ar + + + 4470 + ES + 953_AR + 559600 + + + 4471 + ES + 953_AR + 593600 + + + + + 953_hi + + + 5490 + ES + 953_HI + 594600 + + + 5491 + ES + 953_HI + 595600 + + + + + 954_ar + + + 6520 + EG + 954_AR + 425100 + + + 6521 + EG + 954_AR + 425200 + + + + + 954_hi + + + 8756 + EG + 954_HI + 444400 + + + 8757 + EG + 954_HI + 444500 + + + + + 546_ar + + + 10990 + ES + 546_AR + 1314300 + + + 10991 + ES + 546_AR + 1314300 + + + + + 546_hi + + + 15974 + ES + 546_HI + 1243500 + + + 15975 + ES + 546_HI + 1242500 + + + + + 708_ar + + + 20958 + ES + 708_AR + 1515300 + + + 20959 + ES + 708_AR + 1515800 + + + + + 708_hi + + + 25585 + ES + 708_HI + 1449700 + + + 25586 + ES + 708_HI + 1448700 + + + + + + + 30000000 + + + 95000.0 + + + 0 + EG + 060116_AR + 47500 + + + 1 + EG + 600116_AR + 47500 + + + + + 91400.0 + + + 86 + EG + 600116_AR + 45700 + + + 87 + EG + 600116_AR + 45700 + + + + + 104800.0 + + + 172 + EG + 600116_AR + 52400 + + + 173 + EG + 001166_AR + 52400 + + + + + 99400.0 + + + 217 + EG + 001164_AR + 49700 + + + 218 + EG + 040116_AR + 49700 + + + + + 109600.0 + + + 262 + EG + 004116_AR + 54800 + + + 263 + EG + 040116_AR + 54800 + + + + + 102400.0 + + + 307 + EG + 004116_AR + 51200 + + + 308 + EG + 001416_AR + 51200 + + + + + 116800.0 + + + 352 + EG + 001416_AR + 58400 + + + 353 + EG + 004116_AR + 58400 + + + + + 107800.0 + + + 438 + EG + 004116_AR + 53900 + + + 439 + EG + 040116_AR + 53900 + + + + + 136200.0 + + + 524 + EG + 004116_AR + 68100 + + + 525 + EG + 0014416_AR + 68100 + + + + + 131400.0 + + + 600 + EG + 001164_AR + 65700 + + + 601 + EG + 001416_AR + 65700 + + + + + + + 30000000 + + + 68298 + FR + 0426_OA + 1234070 + + + 68299 + FR + 0426_OA + 1234070 + + + + + \ No newline at end of file diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/response/QueryResponseTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/response/QueryResponseTest.java index b8230eff37c..d2cea4f24ef 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/response/QueryResponseTest.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/response/QueryResponseTest.java @@ -28,9 +28,10 @@ import org.junit.Test; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; +import java.util.List; /** - * Simple test for Date facet support in QueryResponse + * A few tests for parsing Solr response in QueryResponse * * @since solr 1.3 */ @@ -113,4 +114,106 @@ public class QueryResponseTest extends LuceneTestCase { assertEquals(0, manufacturedateDt.getCounts().get(2).getCount()); } + @Test + public void testGroupResponse() throws Exception { + XMLResponseParser parser = new XMLResponseParser(); + InputStream is = new SolrResourceLoader(null, null).openResource("solrj/sampleGroupResponse.xml"); + assertNotNull(is); + Reader in = new InputStreamReader(is, "UTF-8"); + NamedList response = parser.processResponse(in); + in.close(); + + QueryResponse qr = new QueryResponse(response, null); + assertNotNull(qr); + GroupResponse groupResponse = qr.getGroupResponse(); + assertNotNull(groupResponse); + List commands = groupResponse.getValues(); + assertNotNull(commands); + assertEquals(3, commands.size()); + + GroupCommand fieldCommand = commands.get(0); + assertEquals("acco_id", fieldCommand.getName()); + assertEquals(30000000, fieldCommand.getMatches()); + assertEquals(5687, fieldCommand.getNGroups().intValue()); + List fieldCommandGroups = fieldCommand.getValues(); + assertEquals(10, fieldCommandGroups.size()); + assertEquals("116_ar", fieldCommandGroups.get(0).getGroupValue()); + assertEquals(2, fieldCommandGroups.get(0).getResult().size()); + assertEquals(2236, fieldCommandGroups.get(0).getResult().getNumFound()); + assertEquals("116_hi", fieldCommandGroups.get(1).getGroupValue()); + assertEquals(2, fieldCommandGroups.get(1).getResult().size()); + assertEquals(2234, fieldCommandGroups.get(1).getResult().getNumFound()); + assertEquals("953_ar", fieldCommandGroups.get(2).getGroupValue()); + assertEquals(2, fieldCommandGroups.get(2).getResult().size()); + assertEquals(1020, fieldCommandGroups.get(2).getResult().getNumFound()); + assertEquals("953_hi", fieldCommandGroups.get(3).getGroupValue()); + assertEquals(2, fieldCommandGroups.get(3).getResult().size()); + assertEquals(1030, fieldCommandGroups.get(3).getResult().getNumFound()); + assertEquals("954_ar", fieldCommandGroups.get(4).getGroupValue()); + assertEquals(2, fieldCommandGroups.get(4).getResult().size()); + assertEquals(2236, fieldCommandGroups.get(4).getResult().getNumFound()); + assertEquals("954_hi", fieldCommandGroups.get(5).getGroupValue()); + assertEquals(2, fieldCommandGroups.get(5).getResult().size()); + assertEquals(2234, fieldCommandGroups.get(5).getResult().getNumFound()); + assertEquals("546_ar", fieldCommandGroups.get(6).getGroupValue()); + assertEquals(2, fieldCommandGroups.get(6).getResult().size()); + assertEquals(4984, fieldCommandGroups.get(6).getResult().getNumFound()); + assertEquals("546_hi", fieldCommandGroups.get(7).getGroupValue()); + assertEquals(2, fieldCommandGroups.get(7).getResult().size()); + assertEquals(4984, fieldCommandGroups.get(7).getResult().getNumFound()); + assertEquals("708_ar", fieldCommandGroups.get(8).getGroupValue()); + assertEquals(2, fieldCommandGroups.get(8).getResult().size()); + assertEquals(4627, fieldCommandGroups.get(8).getResult().getNumFound()); + assertEquals("708_hi", fieldCommandGroups.get(9).getGroupValue()); + assertEquals(2, fieldCommandGroups.get(9).getResult().size()); + assertEquals(4627, fieldCommandGroups.get(9).getResult().getNumFound()); + + GroupCommand funcCommand = commands.get(1); + assertEquals("sum(price, price)", funcCommand.getName()); + assertEquals(30000000, funcCommand.getMatches()); + assertNull(funcCommand.getNGroups()); + List funcCommandGroups = funcCommand.getValues(); + assertEquals(10, funcCommandGroups.size()); + assertEquals("95000.0", funcCommandGroups.get(0).getGroupValue()); + assertEquals(2, funcCommandGroups.get(0).getResult().size()); + assertEquals(43666, funcCommandGroups.get(0).getResult().getNumFound()); + assertEquals("91400.0", funcCommandGroups.get(1).getGroupValue()); + assertEquals(2, funcCommandGroups.get(1).getResult().size()); + assertEquals(27120, funcCommandGroups.get(1).getResult().getNumFound()); + assertEquals("104800.0", funcCommandGroups.get(2).getGroupValue()); + assertEquals(2, funcCommandGroups.get(2).getResult().size()); + assertEquals(34579, funcCommandGroups.get(2).getResult().getNumFound()); + assertEquals("99400.0", funcCommandGroups.get(3).getGroupValue()); + assertEquals(2, funcCommandGroups.get(3).getResult().size()); + assertEquals(40519, funcCommandGroups.get(3).getResult().getNumFound()); + assertEquals("109600.0", funcCommandGroups.get(4).getGroupValue()); + assertEquals(2, funcCommandGroups.get(4).getResult().size()); + assertEquals(36203, funcCommandGroups.get(4).getResult().getNumFound()); + assertEquals("102400.0", funcCommandGroups.get(5).getGroupValue()); + assertEquals(2, funcCommandGroups.get(5).getResult().size()); + assertEquals(37852, funcCommandGroups.get(5).getResult().getNumFound()); + assertEquals("116800.0", funcCommandGroups.get(6).getGroupValue()); + assertEquals(2, funcCommandGroups.get(6).getResult().size()); + assertEquals(40393, funcCommandGroups.get(6).getResult().getNumFound()); + assertEquals("107800.0", funcCommandGroups.get(7).getGroupValue()); + assertEquals(2, funcCommandGroups.get(7).getResult().size()); + assertEquals(41639, funcCommandGroups.get(7).getResult().getNumFound()); + assertEquals("136200.0", funcCommandGroups.get(8).getGroupValue()); + assertEquals(2, funcCommandGroups.get(8).getResult().size()); + assertEquals(25929, funcCommandGroups.get(8).getResult().getNumFound()); + assertEquals("131400.0", funcCommandGroups.get(9).getGroupValue()); + assertEquals(2, funcCommandGroups.get(9).getResult().size()); + assertEquals(29179, funcCommandGroups.get(9).getResult().getNumFound()); + + GroupCommand queryCommand = commands.get(2); + assertEquals("country:fr", queryCommand.getName()); + assertNull(queryCommand.getNGroups()); + assertEquals(30000000, queryCommand.getMatches()); + List queryCommandGroups = queryCommand.getValues(); + assertEquals(1, queryCommandGroups.size()); + assertEquals("country:fr", queryCommandGroups.get(0).getGroupValue()); + assertEquals(2, queryCommandGroups.get(0).getResult().size()); + assertEquals(57074, queryCommandGroups.get(0).getResult().getNumFound()); + } + }