| /** |
| * 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.lucene.util.BytesRef; |
| 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.response.SolrQueryResponse; |
| import org.apache.solr.search.DocListAndSet; |
| import org.apache.solr.search.QParser; |
| import org.apache.solr.search.SortSpec; |
| import org.apache.solr.search.SolrIndexSearcher; |
| import org.apache.solr.search.grouping.GroupingSpecification; |
| import org.apache.solr.search.grouping.distributed.command.QueryCommandResult; |
| |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| /** |
| * 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; |
| |
| ////////////////////////////////////////////////////////// |
| ////////////////////////////////////////////////////////// |
| //// 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>, String>> searchGroupToShard = new HashMap<String, Map<SearchGroup<String>, 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>(); |
| |
| /** |
| * 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 ); |
| } |
| } |
| } |