SOLR-13156: support facet.sort for facet.field={!terms=foo,bar}field

This commit is contained in:
Mikhail Khludnev 2019-01-27 15:05:40 +03:00
parent 7713a4f245
commit 43f2723213
4 changed files with 64 additions and 12 deletions

View File

@ -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
----------------------

View File

@ -18,6 +18,7 @@ package org.apache.solr.request;
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;
@ -35,6 +36,7 @@ import java.util.concurrent.FutureTask;
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;
@ -861,22 +863,39 @@ public class SimpleFacets {
}
/**
* Computes the term->count counts for the specified term values relative to the
* Computes the term->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();
}
return res;
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()));
}
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

View File

@ -900,5 +900,36 @@ public class TestFaceting extends SolrTestCaseJ4 {
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']");
}
}

View File

@ -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.
@ -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