public void transform( Map<String, ?> result, SolrQueryResponse response, GroupingSpecification groupingSpecification, SolrDocumentSource solrDocumentSource) { Object value = result.get(groupingSpecification.getFields()[0]); if (TopGroups.class.isInstance(value)) { @SuppressWarnings("unchecked") TopGroups<BytesRef> topGroups = (TopGroups<BytesRef>) value; SolrDocumentList docList = new SolrDocumentList(); docList.setStart(groupingSpecification.getOffset()); docList.setNumFound(topGroups.totalHitCount); Float maxScore = Float.NEGATIVE_INFINITY; for (GroupDocs<BytesRef> group : topGroups.groups) { for (ScoreDoc scoreDoc : group.scoreDocs) { if (maxScore < scoreDoc.score) { maxScore = scoreDoc.score; } docList.add(solrDocumentSource.retrieve(scoreDoc)); } } if (maxScore != Float.NEGATIVE_INFINITY) { docList.setMaxScore(maxScore); } response.add("response", docList); } }
@Before public void setUp() throws Exception { Answer<GroupCollapseSummary> answer = new Answer<GroupCollapseSummary>() { @Override public GroupCollapseSummary answer(InvocationOnMock invocation) throws Throwable { Object[] args = invocation.getArguments(); DummyGroupCollapseSummary dummyObject = new DummyGroupCollapseSummary( (String) args[0], (SolrIndexSearcher) args[1], (Set<String>) args[2], (String) args[3]); return dummyObject; } }; PowerMockito.whenNew(GroupCollapseSummary.class).withAnyArguments().thenAnswer(answer); initMocks(this); schema = PowerMockito.mock(IndexSchema.class); rb.req = req; rb.rsp = rsp; when(rb.getGroupingSpec()).thenReturn(groupSpec); when(req.getParams()).thenReturn(params); when(req.getSchema()).thenReturn(schema); when(req.getSearcher()).thenReturn(searcher); mockResponse(); when(schema.getFieldType(FIELD_PRICE)).thenReturn(priceType); when(schema.getFieldType(FIELD_DISCOUNT)).thenReturn(discountType); when(schema.getFieldType(FIELD_CLOSEOUT)).thenReturn(booleanType); when(schema.getFieldType(FIELD_COLOR)).thenReturn(stringType); when(schema.getFieldType(FIELD_COLORFAMILY)).thenReturn(stringType); numericType = PowerMockito.mock(org.apache.lucene.document.FieldType.NumericType.class); when(priceType.getNumericType()).thenReturn(numericType); when(priceType.getTypeName()).thenReturn("tfloat"); when(discountType.getNumericType()).thenReturn(numericType); when(discountType.getTypeName()).thenReturn("tint"); when(booleanType.getTypeName()).thenReturn("boolean"); when(stringType.getTypeName()).thenReturn("string"); when(groupSpec.getFields()).thenReturn(new String[] {"productId"}); }
public NamedList<Integer> getGroupedCounts( SolrIndexSearcher searcher, DocSet base, String field, boolean multiToken, int offset, int limit, int mincount, boolean missing, String sort, String prefix, String contains, boolean ignoreCase) throws IOException { GroupingSpecification groupingSpecification = rb.getGroupingSpec(); final String groupField = groupingSpecification != null ? groupingSpecification.getFields()[0] : null; if (groupField == null) { throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "Specify the group.field as parameter or local parameter"); } BytesRef prefixBytesRef = prefix != null ? new BytesRef(prefix) : null; final TermGroupFacetCollector collector = TermGroupFacetCollector.createTermGroupFacetCollector( groupField, field, multiToken, prefixBytesRef, 128); SchemaField sf = searcher.getSchema().getFieldOrNull(groupField); if (sf != null && sf.hasDocValues() == false && sf.multiValued() == false && sf.getType().getNumericType() != null) { // it's a single-valued numeric field: we must currently create insanity :( // there isn't a GroupedFacetCollector that works on numerics right now... searcher.search( base.getTopFilter(), new FilterCollector(collector) { @Override public LeafCollector getLeafCollector(LeafReaderContext context) throws IOException { LeafReader insane = Insanity.wrapInsanity(context.reader(), groupField); return in.getLeafCollector(insane.getContext()); } }); } else { searcher.search(base.getTopFilter(), collector); } boolean orderByCount = sort.equals(FacetParams.FACET_SORT_COUNT) || sort.equals(FacetParams.FACET_SORT_COUNT_LEGACY); TermGroupFacetCollector.GroupedFacetResult result = collector.mergeSegmentResults( limit < 0 ? Integer.MAX_VALUE : (offset + limit), mincount, orderByCount); CharsRefBuilder charsRef = new CharsRefBuilder(); FieldType facetFieldType = searcher.getSchema().getFieldType(field); NamedList<Integer> facetCounts = new NamedList<>(); List<TermGroupFacetCollector.FacetEntry> scopedEntries = result.getFacetEntries(offset, limit < 0 ? Integer.MAX_VALUE : limit); for (TermGroupFacetCollector.FacetEntry facetEntry : scopedEntries) { // :TODO:can we do contains earlier than this to make it more efficient? if (contains != null && !contains(facetEntry.getValue().utf8ToString(), contains, ignoreCase)) { continue; } facetFieldType.indexedToReadable(facetEntry.getValue(), charsRef); facetCounts.add(charsRef.toString(), facetEntry.getCount()); } if (missing) { facetCounts.add(null, result.getTotalMissingCount()); } return facetCounts; }
@Override public void prepare(ResponseBuilder rb) throws IOException { SolrQueryRequest req = rb.req; SolrParams params = req.getParams(); // A runtime param can skip if (!params.getBool(QueryElevationParams.ENABLE, true)) { return; } boolean exclusive = params.getBool(QueryElevationParams.EXCLUSIVE, false); // A runtime parameter can alter the config value for forceElevation boolean force = params.getBool(QueryElevationParams.FORCE_ELEVATION, forceElevation); boolean markExcludes = params.getBool(QueryElevationParams.MARK_EXCLUDES, false); String boostStr = params.get(QueryElevationParams.IDS); String exStr = params.get(QueryElevationParams.EXCLUDE); Query query = rb.getQuery(); String qstr = rb.getQueryString(); if (query == null || qstr == null) { return; } ElevationObj booster = null; try { if (boostStr != null || exStr != null) { List<String> boosts = (boostStr != null) ? StrUtils.splitSmart(boostStr, ",", true) : new ArrayList<String>(0); List<String> excludes = (exStr != null) ? StrUtils.splitSmart(exStr, ",", true) : new ArrayList<String>(0); booster = new ElevationObj(qstr, boosts, excludes); } else { IndexReader reader = req.getSearcher().getIndexReader(); qstr = getAnalyzedQuery(qstr); booster = getElevationMap(reader, req.getCore()).get(qstr); } } catch (Exception ex) { throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error loading elevation", ex); } if (booster != null) { rb.req.getContext().put(BOOSTED, booster.ids); // Change the query to insert forced documents if (exclusive == true) { // we only want these results rb.setQuery(booster.include); } else { BooleanQuery newq = new BooleanQuery(true); newq.add(query, BooleanClause.Occur.SHOULD); newq.add(booster.include, BooleanClause.Occur.SHOULD); if (booster.exclude != null) { if (markExcludes == false) { for (TermQuery tq : booster.exclude) { newq.add(new BooleanClause(tq, BooleanClause.Occur.MUST_NOT)); } } else { // we are only going to mark items as excluded, not actually exclude them. This works // with the EditorialMarkerFactory rb.req.getContext().put(EXCLUDED, booster.excludeIds); } } rb.setQuery(newq); } ElevationComparatorSource comparator = new ElevationComparatorSource(booster); // if the sort is 'score desc' use a custom sorting method to // insert documents in their proper place SortSpec sortSpec = rb.getSortSpec(); if (sortSpec.getSort() == null) { sortSpec.setSortAndFields( new Sort( new SortField[] { new SortField("_elevate_", comparator, true), new SortField(null, SortField.Type.SCORE, false) }), Arrays.asList(new SchemaField[2])); } else { // Check if the sort is based on score SortSpec modSortSpec = this.modifySortSpec(sortSpec, force, comparator); if (null != modSortSpec) { rb.setSortSpec(modSortSpec); } } // alter the sorting in the grouping specification if there is one GroupingSpecification groupingSpec = rb.getGroupingSpec(); if (groupingSpec != null) { SortField[] groupSort = groupingSpec.getGroupSort().getSort(); Sort modGroupSort = this.modifySort(groupSort, force, comparator); if (modGroupSort != null) { groupingSpec.setGroupSort(modGroupSort); } SortField[] withinGroupSort = groupingSpec.getSortWithinGroup().getSort(); Sort modWithinGroupSort = this.modifySort(withinGroupSort, force, comparator); if (modWithinGroupSort != null) { groupingSpec.setSortWithinGroup(modWithinGroupSort); } } } // Add debugging information if (rb.isDebug()) { List<String> match = null; if (booster != null) { // Extract the elevated terms into a list match = new ArrayList<String>(booster.priority.size()); for (Object o : booster.include.clauses()) { TermQuery tq = (TermQuery) ((BooleanClause) o).getQuery(); match.add(tq.getTerm().text()); } } SimpleOrderedMap<Object> dbg = new SimpleOrderedMap<Object>(); dbg.add("q", qstr); dbg.add("match", match); if (rb.isDebugQuery()) { rb.addDebugInfo("queryBoosting", dbg); } } }