/solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java
Java | 511 lines | 357 code | 87 blank | 67 comment | 39 complexity | a29f6743158a31c91d5e6a1d260b1dee MD5 | raw file
Possible License(s): LGPL-2.1, CPL-1.0, MPL-2.0-no-copyleft-exception, JSON, Apache-2.0, AGPL-1.0, GPL-2.0, GPL-3.0, MIT, BSD-3-Clause
- /*
- * 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 java.util.ArrayList;
- import java.util.Collection;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
- import org.apache.lucene.search.Query;
- import org.apache.lucene.search.TotalHits;
- 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.SimpleOrderedMap;
- import org.apache.solr.request.SolrQueryRequest;
- import org.apache.solr.request.SolrRequestInfo;
- import org.apache.solr.response.SolrQueryResponse;
- import org.apache.solr.search.CursorMark;
- import org.apache.solr.search.DocListAndSet;
- import org.apache.solr.search.DocSlice;
- import org.apache.solr.search.QParser;
- import org.apache.solr.search.QueryCommand;
- import org.apache.solr.search.QueryResult;
- import org.apache.solr.search.RankQuery;
- import org.apache.solr.search.SortSpec;
- import org.apache.solr.search.grouping.GroupingSpecification;
- import org.apache.solr.search.grouping.distributed.command.QueryCommandResult;
- import org.apache.solr.util.RTimer;
- /**
- * This class is experimental and will be changing in the future.
- *
- *
- * @since solr 1.3
- */
- public class ResponseBuilder
- {
- public SolrQueryRequest req;
- public SolrQueryResponse rsp;
- public boolean doHighlights;
- public boolean doFacets;
- public boolean doExpand;
- public boolean doStats;
- public boolean doTerms;
- public boolean doAnalytics;
- public MergeStrategy mergeFieldHandler;
- private boolean needDocList = false;
- private boolean needDocSet = false;
- private int fieldFlags = 0;
- //private boolean debug = false;
- private boolean debugTimings, debugQuery, debugResults, debugTrack;
- 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 CursorMark cursorMark;
- private CursorMark nextCursorMark;
- private List<MergeStrategy> mergeStrategies;
- private RankQuery rankQuery;
- 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
- boolean isDistrib; // is this a distributed search?
- public String[] shards;
- public String[] slices; // the optional logical ids of the 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 String shortCircuitedURL;
- /**
- * This function will return true if this was a distributed search request.
- */
- public boolean isDistributed() {
- return this.isDistrib;
- }
- 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 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 boolean onePassDistributedQuery;
- public FacetComponent.FacetInfo _facetInfo;
- /* private... components that don't own these shouldn't use them */
- SolrDocumentList _responseDocs;
- StatsInfo _statsInfo;
- TermsComponent.TermsHelper _termsHelper;
- SimpleOrderedMap<List<NamedList<Object>>> _pivots;
- Object _analyticsRequestManager;
- boolean _isOlapAnalytics;
- // Context fields for grouping
- public final Map<String, Collection<SearchGroup<BytesRef>>> mergedSearchGroups = new HashMap<>();
- public final Map<String, Integer> mergedGroupCounts = new HashMap<>();
- public final Map<String, Map<SearchGroup<BytesRef>, Set<String>>> searchGroupToShards = new HashMap<>();
- public final Map<String, TopGroups<BytesRef>> mergedTopGroups = new HashMap<>();
- public final Map<String, QueryCommandResult> mergedQueryCommandResults = new HashMap<>();
- public final Map<Object, SolrDocument> retrievedDocuments = new HashMap<>();
- 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<>();
- }
- debugInfo.add( name, val );
- }
- public void addDebug(Object val, String... path) {
- if( debugInfo == null ) {
- debugInfo = new SimpleOrderedMap<>();
- }
- NamedList<Object> target = debugInfo;
- for (int i=0; i<path.length-1; i++) {
- String elem = path[i];
- NamedList<Object> newTarget = (NamedList<Object>)debugInfo.get(elem);
- if (newTarget == null) {
- newTarget = new SimpleOrderedMap<>();
- target.add(elem, newTarget);
- }
- target = newTarget;
- }
- target.add(path[path.length-1], val);
- }
- //-------------------------------------------------------------------------
- //-------------------------------------------------------------------------
- public boolean isDebug() {
- return debugQuery || debugTimings || debugResults || debugTrack;
- }
- /**
- *
- * @return true if all debugging options are on
- */
- public boolean isDebugAll(){
- return debugQuery && debugTimings && debugResults && debugTrack;
- }
- public void setDebug(boolean dbg){
- debugQuery = dbg;
- debugTimings = dbg;
- debugResults = dbg;
- debugTrack = dbg;
- }
- public void addMergeStrategy(MergeStrategy mergeStrategy) {
- if(mergeStrategies == null) {
- mergeStrategies = new ArrayList();
- }
- mergeStrategies.add(mergeStrategy);
- }
- public List<MergeStrategy> getMergeStrategies() {
- return this.mergeStrategies;
- }
- public RankQuery getRankQuery() {
- return rankQuery;
- }
- public void setRankQuery(RankQuery rankQuery) {
- this.rankQuery = rankQuery;
- }
- public void setResponseDocs(SolrDocumentList _responseDocs) {
- this._responseDocs = _responseDocs;
- }
-
- public SolrDocumentList getResponseDocs() {
- return this._responseDocs;
- }
- public boolean isDebugTrack() {
- return debugTrack;
- }
- public void setDebugTrack(boolean debugTrack) {
- this.debugTrack = debugTrack;
- }
- 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 sortSpec) {
- this.sortSpec = sortSpec;
- }
- 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;
- }
- /**
- * Creates a SolrIndexSearcher.QueryCommand from this
- * ResponseBuilder. TimeAllowed is left unset.
- */
- public QueryCommand createQueryCommand() {
- QueryCommand cmd = new QueryCommand();
- cmd.setQuery(wrap(getQuery()))
- .setFilterList(getFilters())
- .setSort(getSortSpec().getSort())
- .setOffset(getSortSpec().getOffset())
- .setLen(getSortSpec().getCount())
- .setFlags(getFieldFlags())
- .setNeedDocSet(isNeedDocSet())
- .setCursorMark(getCursorMark());
- return cmd;
- }
- /** Calls {@link RankQuery#wrap(Query)} if there's a rank query, otherwise just returns the query. */
- public Query wrap(Query q) {
- if(this.rankQuery != null) {
- return this.rankQuery.wrap(q);
- } else {
- return q;
- }
- }
- /**
- * Sets results from a SolrIndexSearcher.QueryResult.
- */
- public void setResult(QueryResult result) {
- setResults(result.getDocListAndSet());
- if (result.isPartialResults()) {
- rsp.getResponseHeader().asShallowMap()
- .put(SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY, Boolean.TRUE);
- if(getResults() != null && getResults().docList==null) {
- getResults().docList = new DocSlice(0, 0, new int[] {}, new float[] {}, 0, 0, TotalHits.Relation.EQUAL_TO);
- }
- }
- final Boolean segmentTerminatedEarly = result.getSegmentTerminatedEarly();
- if (segmentTerminatedEarly != null) {
- rsp.getResponseHeader().add(SolrQueryResponse.RESPONSE_HEADER_SEGMENT_TERMINATED_EARLY_KEY, segmentTerminatedEarly);
- }
- if (null != cursorMark) {
- assert null != result.getNextCursorMark() : "using cursor but no next cursor set";
- this.setNextCursorMark(result.getNextCursorMark());
- }
- }
-
- public long getNumberDocumentsFound() {
- if (_responseDocs == null) {
- return 0;
- }
- return _responseDocs.getNumFound();
- }
- public CursorMark getCursorMark() {
- return cursorMark;
- }
- public void setCursorMark(CursorMark cursorMark) {
- this.cursorMark = cursorMark;
- }
- public CursorMark getNextCursorMark() {
- return nextCursorMark;
- }
- public void setNextCursorMark(CursorMark nextCursorMark) {
- this.nextCursorMark = nextCursorMark;
- }
- public void setAnalytics(boolean doAnalytics) {
- this.doAnalytics = doAnalytics;
- }
- public boolean isAnalytics() {
- return this.doAnalytics;
- }
- public void setAnalyticsRequestManager(Object analyticsRequestManager) {
- this._analyticsRequestManager = analyticsRequestManager;
- }
- public Object getAnalyticsRequestManager() {
- return this._analyticsRequestManager;
- }
- public void setOlapAnalytics(boolean isOlapAnalytics) {
- this._isOlapAnalytics = isOlapAnalytics;
- }
- public boolean isOlapAnalytics() {
- return this._isOlapAnalytics;
- }
- }