blob: 0e81eba8caa730c7b0b7567d1525a1d6481580ae [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.solr.handler.component;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.grouping.SearchGroup;
import org.apache.lucene.search.grouping.TopGroups;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.RTimer;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrRequestInfo;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.search.DocListAndSet;
import org.apache.solr.search.QParser;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.search.SortSpec;
import org.apache.solr.search.grouping.GroupingSpecification;
import org.apache.solr.search.grouping.distributed.command.QueryCommandResult;
import java.util.*;
/**
* This class is experimental and will be changing in the future.
*
* @version $Id$
* @since solr 1.3
*/
public class ResponseBuilder
{
public SolrQueryRequest req;
public SolrQueryResponse rsp;
public boolean doHighlights;
public boolean doFacets;
public boolean doStats;
public boolean doTerms;
private boolean needDocList = false;
private boolean needDocSet = false;
private int fieldFlags = 0;
private boolean debug = false;
private QParser qparser = null;
private String queryString = null;
private Query query = null;
private List<Query> filters = null;
private SortSpec sortSpec = null;
private GroupingSpecification groupingSpec;
private DocListAndSet results = null;
private NamedList<Object> debugInfo = null;
private RTimer timer = null;
private Query highlightQuery = null;
public List<SearchComponent> components;
SolrRequestInfo requestInfo;
public ResponseBuilder(SolrQueryRequest req, SolrQueryResponse rsp, List<SearchComponent> components)
{
this.req = req;
this.rsp = rsp;
this.components = components;
this.requestInfo = SolrRequestInfo.getRequestInfo();
}
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
//// Distributed Search section
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
public static final String FIELD_SORT_VALUES = "fsv";
public static final String SHARDS = "shards";
public static final String IDS = "ids";
/***
public static final String NUMDOCS = "nd";
public static final String DOCFREQS = "tdf";
public static final String TERMS = "terms";
public static final String EXTRACT_QUERY_TERMS = "eqt";
public static final String LOCAL_SHARD = "local";
public static final String DOC_QUERY = "dq";
***/
public static int STAGE_START = 0;
public static int STAGE_PARSE_QUERY = 1000;
public static int STAGE_TOP_GROUPS = 1500;
public static int STAGE_EXECUTE_QUERY = 2000;
public static int STAGE_GET_FIELDS = 3000;
public static int STAGE_DONE = Integer.MAX_VALUE;
public int stage; // What stage is this current request at?
//The address of the Shard
public String[] shards;
public int shards_rows = -1;
public int shards_start = -1;
public List<ShardRequest> outgoing; // requests to be sent
public List<ShardRequest> finished; // requests that have received responses from all shards
public int getShardNum(String shard) {
for (int i=0; i<shards.length; i++) {
if (shards[i]==shard || shards[i].equals(shard)) return i;
}
return -1;
}
public void addRequest(SearchComponent me, ShardRequest sreq) {
outgoing.add(sreq);
if ((sreq.purpose & ShardRequest.PURPOSE_PRIVATE)==0) {
// if this isn't a private request, let other components modify it.
for (SearchComponent component : components) {
if (component != me) {
component.modifyRequest(this, me, sreq);
}
}
}
}
public GlobalCollectionStat globalCollectionStat;
public Map<Object, ShardDoc> resultIds;
// Maps uniqueKeyValue to ShardDoc, which may be used to
// determine order of the doc or uniqueKey in the final
// returned sequence.
// Only valid after STAGE_EXECUTE_QUERY has completed.
public FacetComponent.FacetInfo _facetInfo;
/* private... components that don't own these shouldn't use them */
SolrDocumentList _responseDocs;
StatsInfo _statsInfo;
TermsComponent.TermsHelper _termsHelper;
// Context fields for grouping
public final Map<String, Collection<SearchGroup<String>>> mergedSearchGroups = new HashMap<String, Collection<SearchGroup<String>>>();
public final Map<String, Map<SearchGroup<String>, Set<String>>> searchGroupToShards = new HashMap<String, Map<SearchGroup<String>, Set<String>>>();
public final Map<String, TopGroups<String>> mergedTopGroups = new HashMap<String, TopGroups<String>>();
public final Map<String, QueryCommandResult> mergedQueryCommandResults = new HashMap<String, QueryCommandResult>();
public final Map<Object, SolrDocument> retrievedDocuments = new HashMap<Object, SolrDocument>();
public int totalHitCount; // Hit count used when distributed grouping is performed.
// Used for timeAllowed parameter. First phase elapsed time is subtracted from the time allowed for the second phase.
public int firstPhaseElapsedTime;
/**
* Utility function to add debugging info. This will make sure a valid
* debugInfo exists before adding to it.
*/
public void addDebugInfo( String name, Object val )
{
if( debugInfo == null ) {
debugInfo = new SimpleOrderedMap<Object>();
}
debugInfo.add( name, val );
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
public boolean isDebug() {
return debug;
}
public void setDebug(boolean debug) {
this.debug = debug;
}
public NamedList<Object> getDebugInfo() {
return debugInfo;
}
public void setDebugInfo(NamedList<Object> debugInfo) {
this.debugInfo = debugInfo;
}
public int getFieldFlags() {
return fieldFlags;
}
public void setFieldFlags(int fieldFlags) {
this.fieldFlags = fieldFlags;
}
public List<Query> getFilters() {
return filters;
}
public void setFilters(List<Query> filters) {
this.filters = filters;
}
public Query getHighlightQuery() {
return highlightQuery;
}
public void setHighlightQuery(Query highlightQuery) {
this.highlightQuery = highlightQuery;
}
public boolean isNeedDocList() {
return needDocList;
}
public void setNeedDocList(boolean needDocList) {
this.needDocList = needDocList;
}
public boolean isNeedDocSet() {
return needDocSet;
}
public void setNeedDocSet(boolean needDocSet) {
this.needDocSet = needDocSet;
}
public QParser getQparser() {
return qparser;
}
public void setQparser(QParser qparser) {
this.qparser = qparser;
}
public String getQueryString() {
return queryString;
}
public void setQueryString(String qstr) {
this.queryString = qstr;
}
public Query getQuery() {
return query;
}
public void setQuery(Query query) {
this.query = query;
}
public DocListAndSet getResults() {
return results;
}
public void setResults(DocListAndSet results) {
this.results = results;
}
public SortSpec getSortSpec() {
return sortSpec;
}
public void setSortSpec(SortSpec sort) {
this.sortSpec = sort;
}
public GroupingSpecification getGroupingSpec() {
return groupingSpec;
}
public void setGroupingSpec(GroupingSpecification groupingSpec) {
this.groupingSpec = groupingSpec;
}
public boolean grouping() {
return groupingSpec != null;
}
public RTimer getTimer() {
return timer;
}
public void setTimer(RTimer timer) {
this.timer = timer;
}
public static class GlobalCollectionStat {
public final long numDocs;
public final Map<String, Long> dfMap;
public GlobalCollectionStat(int numDocs, Map<String, Long> dfMap) {
this.numDocs = numDocs;
this.dfMap = dfMap;
}
}
/**
* Creates a SolrIndexSearcher.QueryCommand from this
* ResponseBuilder. TimeAllowed is left unset.
*/
public SolrIndexSearcher.QueryCommand getQueryCommand() {
SolrIndexSearcher.QueryCommand cmd = new SolrIndexSearcher.QueryCommand();
cmd.setQuery( getQuery() )
.setFilterList( getFilters() )
.setSort( getSortSpec().getSort() )
.setOffset( getSortSpec().getOffset() )
.setLen( getSortSpec().getCount() )
.setFlags( getFieldFlags() )
.setNeedDocSet( isNeedDocSet() );
return cmd;
}
/**
* Sets results from a SolrIndexSearcher.QueryResult.
*/
public void setResult( SolrIndexSearcher.QueryResult result ) {
setResults( result.getDocListAndSet() );
if( result.isPartialResults() ) {
rsp.getResponseHeader().add( "partialResults", Boolean.TRUE );
}
}
}