org.apache.solr.handler.component.ResponseBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.solr.handler.component.ResponseBuilder.java

Source

/*
 * 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.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);
            }
        }
        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;
    }
}