/** * 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.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.SolrIndexSearcher; import org.apache.solr.search.SortSpec; import org.apache.solr.util.SolrPluginUtils; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * This class is experimental and will be changing in the future. * * @version $Id: ResponseBuilder.java 992128 2010-09-02 21:59:19Z gsingers $ * @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 boolean debugTimings, debugQuery, debugResults; private QParser qparser = null; private String queryString = null; private Query query = null; private List<Query> filters = null; private SortSpec sortSpec = null; 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_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; 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; /** * 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 debugQuery || debugTimings || debugResults; } /** * * @return true if all debugging options are on */ public boolean isDebugAll(){ return debugQuery && debugTimings && debugResults; } public void setDebug(boolean dbg){ debugQuery = dbg; debugTimings = dbg; debugResults = dbg; } public boolean isDebugTimings() { return debugTimings; } public void setDebugTimings(boolean debugTimings) { this.debugTimings = debugTimings; } public boolean isDebugQuery() { return debugQuery; } public void setDebugQuery(boolean debugQuery) { this.debugQuery = debugQuery; } public boolean isDebugResults() { return debugResults; } public void setDebugResults(boolean debugResults) { this.debugResults = debugResults; } 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 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); } } }