Search in sources :

Example 6 with TopGroups

use of org.apache.lucene.search.grouping.TopGroups in project lucene-solr by apache.

the class TopGroupsShardResponseProcessor method process.

/**
   * {@inheritDoc}
   */
@Override
@SuppressWarnings("unchecked")
public void process(ResponseBuilder rb, ShardRequest shardRequest) {
    Sort groupSort = rb.getGroupingSpec().getGroupSort();
    String[] fields = rb.getGroupingSpec().getFields();
    String[] queries = rb.getGroupingSpec().getQueries();
    Sort withinGroupSort = rb.getGroupingSpec().getSortWithinGroup();
    assert withinGroupSort != null;
    // If group.format=simple group.offset doesn't make sense
    int groupOffsetDefault;
    if (rb.getGroupingSpec().getResponseFormat() == Grouping.Format.simple || rb.getGroupingSpec().isMain()) {
        groupOffsetDefault = 0;
    } else {
        groupOffsetDefault = rb.getGroupingSpec().getWithinGroupOffset();
    }
    int docsPerGroupDefault = rb.getGroupingSpec().getWithinGroupLimit();
    Map<String, List<TopGroups<BytesRef>>> commandTopGroups = new HashMap<>();
    for (String field : fields) {
        commandTopGroups.put(field, new ArrayList<TopGroups<BytesRef>>());
    }
    Map<String, List<QueryCommandResult>> commandTopDocs = new HashMap<>();
    for (String query : queries) {
        commandTopDocs.put(query, new ArrayList<QueryCommandResult>());
    }
    TopGroupsResultTransformer serializer = new TopGroupsResultTransformer(rb);
    NamedList<Object> shardInfo = null;
    if (rb.req.getParams().getBool(ShardParams.SHARDS_INFO, false)) {
        shardInfo = new SimpleOrderedMap<>();
        rb.rsp.getValues().add(ShardParams.SHARDS_INFO, shardInfo);
    }
    for (ShardResponse srsp : shardRequest.responses) {
        SimpleOrderedMap<Object> individualShardInfo = null;
        if (shardInfo != null) {
            individualShardInfo = new SimpleOrderedMap<>();
            if (srsp.getException() != null) {
                Throwable t = srsp.getException();
                if (t instanceof SolrServerException && ((SolrServerException) t).getCause() != null) {
                    t = ((SolrServerException) t).getCause();
                }
                individualShardInfo.add("error", t.toString());
                StringWriter trace = new StringWriter();
                t.printStackTrace(new PrintWriter(trace));
                individualShardInfo.add("trace", trace.toString());
            } else {
            // summary for successful shard response is added down below
            }
            if (srsp.getSolrResponse() != null) {
                individualShardInfo.add("time", srsp.getSolrResponse().getElapsedTime());
            }
            if (srsp.getShardAddress() != null) {
                individualShardInfo.add("shardAddress", srsp.getShardAddress());
            }
            shardInfo.add(srsp.getShard(), individualShardInfo);
        }
        if (rb.req.getParams().getBool(ShardParams.SHARDS_TOLERANT, false) && srsp.getException() != null) {
            if (rb.rsp.getResponseHeader().get(SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY) == null) {
                rb.rsp.getResponseHeader().add(SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY, Boolean.TRUE);
            }
            // continue if there was an error and we're tolerant.  
            continue;
        }
        NamedList<NamedList> secondPhaseResult = (NamedList<NamedList>) srsp.getSolrResponse().getResponse().get("secondPhase");
        if (secondPhaseResult == null)
            continue;
        Map<String, ?> result = serializer.transformToNative(secondPhaseResult, groupSort, withinGroupSort, srsp.getShard());
        int numFound = 0;
        float maxScore = Float.NaN;
        for (String field : commandTopGroups.keySet()) {
            TopGroups<BytesRef> topGroups = (TopGroups<BytesRef>) result.get(field);
            if (topGroups == null) {
                continue;
            }
            if (individualShardInfo != null) {
                // keep track of this when shards.info=true
                numFound += topGroups.totalHitCount;
                if (Float.isNaN(maxScore) || topGroups.maxScore > maxScore)
                    maxScore = topGroups.maxScore;
            }
            commandTopGroups.get(field).add(topGroups);
        }
        for (String query : queries) {
            QueryCommandResult queryCommandResult = (QueryCommandResult) result.get(query);
            if (individualShardInfo != null) {
                // keep track of this when shards.info=true
                numFound += queryCommandResult.getMatches();
                float thisMax = queryCommandResult.getTopDocs().getMaxScore();
                if (Float.isNaN(maxScore) || thisMax > maxScore)
                    maxScore = thisMax;
            }
            commandTopDocs.get(query).add(queryCommandResult);
        }
        if (individualShardInfo != null) {
            // when shards.info=true
            individualShardInfo.add("numFound", numFound);
            individualShardInfo.add("maxScore", maxScore);
        }
    }
    for (String groupField : commandTopGroups.keySet()) {
        List<TopGroups<BytesRef>> topGroups = commandTopGroups.get(groupField);
        if (topGroups.isEmpty()) {
            continue;
        }
        TopGroups<BytesRef>[] topGroupsArr = new TopGroups[topGroups.size()];
        int docsPerGroup = docsPerGroupDefault;
        if (docsPerGroup < 0) {
            docsPerGroup = 0;
            for (TopGroups subTopGroups : topGroups) {
                docsPerGroup += subTopGroups.totalGroupedHitCount;
            }
        }
        rb.mergedTopGroups.put(groupField, TopGroups.merge(topGroups.toArray(topGroupsArr), groupSort, withinGroupSort, groupOffsetDefault, docsPerGroup, TopGroups.ScoreMergeMode.None));
    }
    for (String query : commandTopDocs.keySet()) {
        List<QueryCommandResult> queryCommandResults = commandTopDocs.get(query);
        List<TopDocs> topDocs = new ArrayList<>(queryCommandResults.size());
        int mergedMatches = 0;
        for (QueryCommandResult queryCommandResult : queryCommandResults) {
            topDocs.add(queryCommandResult.getTopDocs());
            mergedMatches += queryCommandResult.getMatches();
        }
        int topN = rb.getGroupingSpec().getOffset() + rb.getGroupingSpec().getLimit();
        final TopDocs mergedTopDocs;
        if (withinGroupSort.equals(Sort.RELEVANCE)) {
            mergedTopDocs = TopDocs.merge(topN, topDocs.toArray(new TopDocs[topDocs.size()]));
        } else {
            mergedTopDocs = TopDocs.merge(withinGroupSort, topN, topDocs.toArray(new TopFieldDocs[topDocs.size()]));
        }
        rb.mergedQueryCommandResults.put(query, new QueryCommandResult(mergedTopDocs, mergedMatches));
    }
    Map<Object, ShardDoc> resultIds = new HashMap<>();
    int i = 0;
    for (TopGroups<BytesRef> topGroups : rb.mergedTopGroups.values()) {
        for (GroupDocs<BytesRef> group : topGroups.groups) {
            for (ScoreDoc scoreDoc : group.scoreDocs) {
                ShardDoc solrDoc = (ShardDoc) scoreDoc;
                // Include the first if there are duplicate IDs
                if (!resultIds.containsKey(solrDoc.id)) {
                    solrDoc.positionInResponse = i++;
                    resultIds.put(solrDoc.id, solrDoc);
                }
            }
        }
    }
    for (QueryCommandResult queryCommandResult : rb.mergedQueryCommandResults.values()) {
        for (ScoreDoc scoreDoc : queryCommandResult.getTopDocs().scoreDocs) {
            ShardDoc solrDoc = (ShardDoc) scoreDoc;
            solrDoc.positionInResponse = i++;
            resultIds.put(solrDoc.id, solrDoc);
        }
    }
    rb.resultIds = resultIds;
}
Also used : HashMap(java.util.HashMap) SolrServerException(org.apache.solr.client.solrj.SolrServerException) ArrayList(java.util.ArrayList) ScoreDoc(org.apache.lucene.search.ScoreDoc) ShardResponse(org.apache.solr.handler.component.ShardResponse) TopDocs(org.apache.lucene.search.TopDocs) StringWriter(java.io.StringWriter) Sort(org.apache.lucene.search.Sort) ArrayList(java.util.ArrayList) NamedList(org.apache.solr.common.util.NamedList) List(java.util.List) TopGroups(org.apache.lucene.search.grouping.TopGroups) BytesRef(org.apache.lucene.util.BytesRef) ShardDoc(org.apache.solr.handler.component.ShardDoc) PrintWriter(java.io.PrintWriter) NamedList(org.apache.solr.common.util.NamedList) QueryCommandResult(org.apache.solr.search.grouping.distributed.command.QueryCommandResult) TopGroupsResultTransformer(org.apache.solr.search.grouping.distributed.shardresultserializer.TopGroupsResultTransformer)

Example 7 with TopGroups

use of org.apache.lucene.search.grouping.TopGroups in project lucene-solr by apache.

the class SimpleEndResultTransformer method transform.

/**
   * {@inheritDoc}
   */
@Override
public void transform(Map<String, ?> result, ResponseBuilder rb, SolrDocumentSource solrDocumentSource) {
    NamedList<Object> commands = new SimpleOrderedMap<>();
    for (Map.Entry<String, ?> entry : result.entrySet()) {
        Object value = entry.getValue();
        if (TopGroups.class.isInstance(value)) {
            @SuppressWarnings("unchecked") TopGroups<BytesRef> topGroups = (TopGroups<BytesRef>) value;
            NamedList<Object> command = new SimpleOrderedMap<>();
            command.add("matches", rb.totalHitCount);
            if (topGroups.totalGroupCount != null) {
                command.add("ngroups", topGroups.totalGroupCount);
            }
            SolrDocumentList docList = new SolrDocumentList();
            docList.setStart(rb.getGroupingSpec().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);
            }
            command.add("doclist", docList);
            commands.add(entry.getKey(), command);
        }
    }
    rb.rsp.add("grouped", commands);
}
Also used : SolrDocumentList(org.apache.solr.common.SolrDocumentList) SimpleOrderedMap(org.apache.solr.common.util.SimpleOrderedMap) ScoreDoc(org.apache.lucene.search.ScoreDoc) TopGroups(org.apache.lucene.search.grouping.TopGroups) SimpleOrderedMap(org.apache.solr.common.util.SimpleOrderedMap) Map(java.util.Map) BytesRef(org.apache.lucene.util.BytesRef)

Aggregations

TopGroups (org.apache.lucene.search.grouping.TopGroups)7 BytesRef (org.apache.lucene.util.BytesRef)7 ScoreDoc (org.apache.lucene.search.ScoreDoc)5 ArrayList (java.util.ArrayList)4 Map (java.util.Map)4 SolrDocumentList (org.apache.solr.common.SolrDocumentList)4 NamedList (org.apache.solr.common.util.NamedList)4 HashMap (java.util.HashMap)3 List (java.util.List)3 GroupDocs (org.apache.lucene.search.grouping.GroupDocs)3 SimpleOrderedMap (org.apache.solr.common.util.SimpleOrderedMap)3 FieldType (org.apache.solr.schema.FieldType)3 QueryCommandResult (org.apache.solr.search.grouping.distributed.command.QueryCommandResult)3 PrintWriter (java.io.PrintWriter)2 StringWriter (java.io.StringWriter)2 Sort (org.apache.lucene.search.Sort)2 TopDocs (org.apache.lucene.search.TopDocs)2 IndexSchema (org.apache.solr.schema.IndexSchema)2 SchemaField (org.apache.solr.schema.SchemaField)2 IOException (java.io.IOException)1