/** {@inheritDoc} */ @Override public void transform( Map<String, ?> result, ResponseBuilder rb, SolrDocumentSource solrDocumentSource) { Object value = result.get(rb.getGroupingSpec().getFields()[0]); if (TopGroups.class.isInstance(value)) { @SuppressWarnings("unchecked") TopGroups<BytesRef> topGroups = (TopGroups<BytesRef>) value; SolrDocumentList docList = new SolrDocumentList(); docList.setStart(rb.getGroupingSpec().getOffset()); docList.setNumFound(rb.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); } rb.rsp.addResponse(docList); } }
public SolrDocumentList readSolrDocumentList(DataInputInputStream dis) throws IOException { SolrDocumentList solrDocs = new SolrDocumentList(); List list = (List) readVal(dis); solrDocs.setNumFound((Long) list.get(0)); solrDocs.setStart((Long) list.get(1)); solrDocs.setMaxScore((Float) list.get(2)); @SuppressWarnings("unchecked") List<SolrDocument> l = (List<SolrDocument>) readVal(dis); solrDocs.addAll(l); return solrDocs; }
protected SolrDocumentList readDocuments(XMLStreamReader parser) throws XMLStreamException { SolrDocumentList docs = new SolrDocumentList(); // Parse the attributes for (int i = 0; i < parser.getAttributeCount(); i++) { String n = parser.getAttributeLocalName(i); String v = parser.getAttributeValue(i); if ("numFound".equals(n)) { docs.setNumFound(Long.parseLong(v)); } else if ("start".equals(n)) { docs.setStart(Long.parseLong(v)); } else if ("maxScore".equals(n)) { docs.setMaxScore(Float.parseFloat(v)); } else if ("sum".equals(n)) { docs.setSum(Double.parseDouble(v)); } else if ("max".equals(n)) { docs.setMax(Double.parseDouble(v)); } else if ("min".equals(n)) { docs.setMin(Double.parseDouble(v)); } } // Read through each document int event; while (true) { event = parser.next(); if (XMLStreamConstants.START_ELEMENT == event) { if (!"doc".equals(parser.getLocalName())) { throw new RuntimeException( "shoudl be doc! " + parser.getLocalName() + " :: " + parser.getLocation()); } docs.add(readDocument(parser)); } else if (XMLStreamConstants.END_ELEMENT == event) { return docs; // only happens once } } }
private void mergeIds(ResponseBuilder rb, ShardRequest sreq) { SortSpec ss = rb.getSortSpec(); Sort sort = ss.getSort(); SortField[] sortFields = null; if (sort != null) sortFields = sort.getSort(); else { sortFields = new SortField[] {SortField.FIELD_SCORE}; } SchemaField uniqueKeyField = rb.req.getSchema().getUniqueKeyField(); // id to shard mapping, to eliminate any accidental dups HashMap<Object, String> uniqueDoc = new HashMap<Object, String>(); // Merge the docs via a priority queue so we don't have to sort *all* of the // documents... we only need to order the top (rows+start) ShardFieldSortedHitQueue queue; queue = new ShardFieldSortedHitQueue(sortFields, ss.getOffset() + ss.getCount()); long numFound = 0; Float maxScore = null; for (ShardResponse srsp : sreq.responses) { SolrDocumentList docs = (SolrDocumentList) srsp.getSolrResponse().getResponse().get("response"); // calculate global maxScore and numDocsFound if (docs.getMaxScore() != null) { maxScore = maxScore == null ? docs.getMaxScore() : Math.max(maxScore, docs.getMaxScore()); } numFound += docs.getNumFound(); NamedList sortFieldValues = (NamedList) (srsp.getSolrResponse().getResponse().get("sort_values")); // go through every doc in this response, construct a ShardDoc, and // put it in the priority queue so it can be ordered. for (int i = 0; i < docs.size(); i++) { SolrDocument doc = docs.get(i); Object id = doc.getFieldValue(uniqueKeyField.getName()); String prevShard = uniqueDoc.put(id, srsp.getShard()); if (prevShard != null) { // duplicate detected numFound--; // For now, just always use the first encountered since we can't currently // remove the previous one added to the priority queue. If we switched // to the Java5 PriorityQueue, this would be easier. continue; // make which duplicate is used deterministic based on shard // if (prevShard.compareTo(srsp.shard) >= 0) { // TODO: remove previous from priority queue // continue; // } } ShardDoc shardDoc = new ShardDoc(); shardDoc.id = id; shardDoc.shard = srsp.getShard(); shardDoc.orderInShard = i; Object scoreObj = doc.getFieldValue("score"); if (scoreObj != null) { if (scoreObj instanceof String) { shardDoc.score = Float.parseFloat((String) scoreObj); } else { shardDoc.score = (Float) scoreObj; } } shardDoc.sortFieldValues = sortFieldValues; queue.insertWithOverflow(shardDoc); } // end for-each-doc-in-response } // end for-each-response // The queue now has 0 -> queuesize docs, where queuesize <= start + rows // So we want to pop the last documents off the queue to get // the docs offset -> queuesize int resultSize = queue.size() - ss.getOffset(); resultSize = Math.max(0, resultSize); // there may not be any docs in range Map<Object, ShardDoc> resultIds = new HashMap<Object, ShardDoc>(); for (int i = resultSize - 1; i >= 0; i--) { ShardDoc shardDoc = (ShardDoc) queue.pop(); shardDoc.positionInResponse = i; // Need the toString() for correlation with other lists that must // be strings (like keys in highlighting, explain, etc) resultIds.put(shardDoc.id.toString(), shardDoc); } SolrDocumentList responseDocs = new SolrDocumentList(); if (maxScore != null) responseDocs.setMaxScore(maxScore); responseDocs.setNumFound(numFound); responseDocs.setStart(ss.getOffset()); // size appropriately for (int i = 0; i < resultSize; i++) responseDocs.add(null); // save these results in a private area so we can access them // again when retrieving stored fields. // TODO: use ResponseBuilder (w/ comments) or the request context? rb.resultIds = resultIds; rb._responseDocs = responseDocs; }
public void merge(ResponseBuilder rb, ShardRequest sreq) { // id to shard mapping, to eliminate any accidental dups HashMap<Object, String> uniqueDoc = new HashMap<>(); NamedList<Object> shardInfo = null; if (rb.req.getParams().getBool(ShardParams.SHARDS_INFO, false)) { shardInfo = new SimpleOrderedMap<>(); rb.rsp.getValues().add(ShardParams.SHARDS_INFO, shardInfo); } IndexSchema schema = rb.req.getSchema(); SchemaField uniqueKeyField = schema.getUniqueKeyField(); long numFound = 0; Float maxScore = null; boolean partialResults = false; List<ShardDoc> shardDocs = new ArrayList(); for (ShardResponse srsp : sreq.responses) { SolrDocumentList docs = null; if (shardInfo != null) { SimpleOrderedMap<Object> nl = new SimpleOrderedMap<>(); if (srsp.getException() != null) { Throwable t = srsp.getException(); if (t instanceof SolrServerException) { t = ((SolrServerException) t).getCause(); } nl.add("error", t.toString()); StringWriter trace = new StringWriter(); t.printStackTrace(new PrintWriter(trace)); nl.add("trace", trace.toString()); if (srsp.getShardAddress() != null) { nl.add("shardAddress", srsp.getShardAddress()); } } else { docs = (SolrDocumentList) srsp.getSolrResponse().getResponse().get("response"); nl.add("numFound", docs.getNumFound()); nl.add("maxScore", docs.getMaxScore()); nl.add("shardAddress", srsp.getShardAddress()); } if (srsp.getSolrResponse() != null) { nl.add("time", srsp.getSolrResponse().getElapsedTime()); } shardInfo.add(srsp.getShard(), nl); } // now that we've added the shard info, let's only proceed if we have no error. if (srsp.getException() != null) { partialResults = true; continue; } if (docs == null) { // could have been initialized in the shards info block above docs = (SolrDocumentList) srsp.getSolrResponse().getResponse().get("response"); } NamedList<?> responseHeader = (NamedList<?>) srsp.getSolrResponse().getResponse().get("responseHeader"); if (responseHeader != null && Boolean.TRUE.equals( responseHeader.get(SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY))) { partialResults = true; } // calculate global maxScore and numDocsFound if (docs.getMaxScore() != null) { maxScore = maxScore == null ? docs.getMaxScore() : Math.max(maxScore, docs.getMaxScore()); } numFound += docs.getNumFound(); SortSpec ss = rb.getSortSpec(); Sort sort = ss.getSort(); NamedList sortFieldValues = (NamedList) (srsp.getSolrResponse().getResponse().get("merge_values")); NamedList unmarshalledSortFieldValues = unmarshalSortValues(ss, sortFieldValues, schema); List lst = (List) unmarshalledSortFieldValues.getVal(0); for (int i = 0; i < docs.size(); i++) { SolrDocument doc = docs.get(i); Object id = doc.getFieldValue(uniqueKeyField.getName()); String prevShard = uniqueDoc.put(id, srsp.getShard()); if (prevShard != null) { // duplicate detected numFound--; // For now, just always use the first encountered since we can't currently // remove the previous one added to the priority queue. If we switched // to the Java5 PriorityQueue, this would be easier. continue; // make which duplicate is used deterministic based on shard // if (prevShard.compareTo(srsp.shard) >= 0) { // TODO: remove previous from priority queue // continue; // } } ShardDoc shardDoc = new ShardDoc(); shardDoc.id = id; shardDoc.shard = srsp.getShard(); shardDoc.orderInShard = i; Object scoreObj = lst.get(i); if (scoreObj != null) { shardDoc.score = ((Integer) scoreObj).floatValue(); } shardDocs.add(shardDoc); } // end for-each-doc-in-response } // end for-each-response Collections.sort( shardDocs, new Comparator<ShardDoc>() { @Override public int compare(ShardDoc o1, ShardDoc o2) { if (o1.score < o2.score) { return 1; } else if (o1.score > o2.score) { return -1; } else { return 0; // To change body of implemented methods use File | Settings | File // Templates. } } }); int resultSize = shardDocs.size(); Map<Object, ShardDoc> resultIds = new HashMap<>(); for (int i = 0; i < shardDocs.size(); i++) { ShardDoc shardDoc = shardDocs.get(i); shardDoc.positionInResponse = i; // Need the toString() for correlation with other lists that must // be strings (like keys in highlighting, explain, etc) resultIds.put(shardDoc.id.toString(), shardDoc); } // Add hits for distributed requests // https://issues.apache.org/jira/browse/SOLR-3518 rb.rsp.addToLog("hits", numFound); SolrDocumentList responseDocs = new SolrDocumentList(); if (maxScore != null) responseDocs.setMaxScore(maxScore); responseDocs.setNumFound(numFound); responseDocs.setStart(0); // size appropriately for (int i = 0; i < resultSize; i++) responseDocs.add(null); // save these results in a private area so we can access them // again when retrieving stored fields. // TODO: use ResponseBuilder (w/ comments) or the request context? rb.resultIds = resultIds; rb.setResponseDocs(responseDocs); if (partialResults) { rb.rsp .getResponseHeader() .add(SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY, Boolean.TRUE); } }