Skip to content

Commit

Permalink
SOLR-13156: support facet.sort for facet.field={!terms=foo,bar}field
Browse files Browse the repository at this point in the history
  • Loading branch information
mkhludnev committed Jan 28, 2019
1 parent 7713a4f commit 43f2723
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 12 deletions.
2 changes: 2 additions & 0 deletions solr/CHANGES.txt
Expand Up @@ -336,6 +336,8 @@ Improvements

* SOLR-13029: solr.hdfs.buffer.size can be configured for HdfsBackupRepository for better performance (Tim Owen via Mikhail Khludnev)

* SOLR-13156: support facet.sort for facet.field={!terms=foo,bar}field. (Konstantin Perikov via Mikhail Khludnev)

Other Changes
----------------------

Expand Down
39 changes: 29 additions & 10 deletions solr/core/src/java/org/apache/solr/request/SimpleFacets.java
Expand Up @@ -18,6 +18,7 @@

import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
Expand All @@ -35,6 +36,7 @@
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.Semaphore;
import java.util.function.Predicate;
import java.util.stream.Stream;

import org.apache.lucene.index.LeafReader;
import org.apache.lucene.index.LeafReaderContext;
Expand Down Expand Up @@ -861,22 +863,39 @@ public NamedList<Object> getFacetFieldCounts()
}

/**
* Computes the term-&gt;count counts for the specified term values relative to the
* Computes the term-&gt;count counts for the specified term values relative to the
*
* @param field the name of the field to compute term counts against
* @param parsed contains the docset to compute term counts relative to
* @param terms a list of term values (in the specified field) to compute the counts for
* @param terms a list of term values (in the specified field) to compute the counts for
*/
protected NamedList<Integer> getListedTermCounts(String field, final ParsedParams parsed, List<String> terms) throws IOException {
SchemaField sf = searcher.getSchema().getField(field);
FieldType ft = sf.getType();
NamedList<Integer> res = new NamedList<>();
for (String term : terms) {
int count = searcher.numDocs(ft.getFieldQuery(null, sf, term), parsed.docs);
res.add(term, count);
protected NamedList<Integer> getListedTermCounts(String field, final ParsedParams parsed, List<String> terms)
throws IOException {
final String sort = parsed.params.getFieldParam(field, FacetParams.FACET_SORT, "empty");
final SchemaField sf = searcher.getSchema().getField(field);
final FieldType ft = sf.getType();
final DocSet baseDocset = parsed.docs;
final NamedList<Integer> res = new NamedList<>();
Stream<String> inputStream = terms.stream();
if (sort.equals(FacetParams.FACET_SORT_INDEX)) { // it might always make sense
inputStream = inputStream.sorted();
}
Stream<SimpleImmutableEntry<String,Integer>> termCountEntries = inputStream
.map((term) -> new SimpleImmutableEntry<>(term, numDocs(term, sf, ft, baseDocset)));
if (sort.equals(FacetParams.FACET_SORT_COUNT)) {
termCountEntries = termCountEntries.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()));
}
return res;
termCountEntries.forEach(e -> res.add(e.getKey(), e.getValue()));
return res;
}

private int numDocs(String term, final SchemaField sf, final FieldType ft, final DocSet baseDocset) {
try {
return searcher.numDocs(ft.getFieldQuery(null, sf, term), baseDocset);
} catch (IOException e1) {
throw new RuntimeException(e1);
}
}

/**
* Returns a count of the documents in the set which do not have any
Expand Down
31 changes: 31 additions & 0 deletions solr/core/src/test/org/apache/solr/request/TestFaceting.java
Expand Up @@ -900,5 +900,36 @@ public void testMultiThreadedFacets() throws Exception {
return null;
});
}

@Test
public void testListedTermCounts() throws Exception {
assertU(adoc("id", "1", "title_ws", "Book1"));
assertU(adoc("id", "2", "title_ws", "Book2"));
assertU(adoc("id", "3", "title_ws", "Book3"));
assertU(adoc("id", "4", "title_ws", "Book2"));
assertU(adoc("id", "5", "title_ws", "Book1"));
assertU(adoc("id", "6", "title_ws", "Book2"));
assertU(commit());

// order is the same as in facet.field, when no facet.sort specified
assertQ(req("q", "*:*", FacetParams.FACET, "true", FacetParams.FACET_FIELD, "{!terms=Book3,Book2,Book1}title_ws"),
"//lst[@name='facet_fields']/lst[@name='title_ws']/int[1][@name='Book3']",
"//lst[@name='facet_fields']/lst[@name='title_ws']/int[2][@name='Book2']",
"//lst[@name='facet_fields']/lst[@name='title_ws']/int[3][@name='Book1']");

// order is by counts, when facet.sort by count specified
assertQ(req("q", "*:*", FacetParams.FACET, "true", FacetParams.FACET_FIELD, "{!terms=Book3,Book2,Book1}title_ws",
"facet.sort", FacetParams.FACET_SORT_COUNT),
"//lst[@name='facet_fields']/lst[@name='title_ws']/int[1][@name='Book2']",
"//lst[@name='facet_fields']/lst[@name='title_ws']/int[2][@name='Book1']",
"//lst[@name='facet_fields']/lst[@name='title_ws']/int[3][@name='Book3']");

// order is by index, when facet.sort by index specified
assertQ(req("q", "*:*", FacetParams.FACET, "true", FacetParams.FACET_FIELD, "{!terms=Book3,Book2,Book1}title_ws",
"facet.sort", FacetParams.FACET_SORT_INDEX),
"//lst[@name='facet_fields']/lst[@name='title_ws']/int[1][@name='Book1']",
"//lst[@name='facet_fields']/lst[@name='title_ws']/int[2][@name='Book2']",
"//lst[@name='facet_fields']/lst[@name='title_ws']/int[3][@name='Book3']");
}
}

4 changes: 2 additions & 2 deletions solr/solr-ref-guide/src/faceting.adoc
Expand Up @@ -79,7 +79,7 @@ There are two options for this parameter.
`index`::: Return the constraints sorted in their index order (lexicographic by indexed term). For terms in the ASCII range, this will be alphabetically sorted.
--
+
The default is `count` if `facet.limit` is greater than 0, otherwise, the default is `index`.
The default is `count` if `facet.limit` is greater than 0, otherwise, the default is `index`. Note that the default logic is changed when <<#limiting-facet-with-certain-terms>>

`facet.limit`::
This parameter specifies the maximum number of constraint counts (essentially, the number of facets for a field that are returned) that should be returned for the facet fields. A negative value means that Solr will return unlimited number of constraint counts.
Expand Down Expand Up @@ -616,7 +616,7 @@ To limit field facet with certain terms specify them comma separated with `terms

`facet.field={!terms='alfa,betta,with\,with\',with space'}symbol`

This parameter disables sorting, facet values are returned in the given order.
This local parameter overrides default logic for `facet.sort`. if `facet.sort` is omitted, facets are returned in the given terms order that might be changed with `index` and `count` values. Note: other parameters might not be fully supported when this parameter is supplied.

== Related Topics

Expand Down

0 comments on commit 43f2723

Please sign in to comment.