Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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.util;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.regex.Pattern;
import org.apache.lucene.document.Document;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.DisjunctionMaxQuery;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.MapSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.common.util.StrUtils;
import org.apache.solr.core.RequestParams;
import org.apache.solr.handler.component.HighlightComponent;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.handler.component.ShardDoc;
import org.apache.solr.handler.component.ShardRequest;
import org.apache.solr.highlight.SolrHighlighter;
import org.apache.solr.parser.QueryParser;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.request.json.RequestUtil;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.search.DocIterator;
import org.apache.solr.search.DocList;
import org.apache.solr.search.DocSet;
import org.apache.solr.search.FieldParams;
import org.apache.solr.search.QParser;
import org.apache.solr.search.QueryParsing;
import org.apache.solr.search.ReturnFields;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.search.SolrQueryParser;
import org.apache.solr.search.SortSpecParsing;
import org.apache.solr.search.SyntaxError;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableMap;
import static java.util.Collections.singletonList;
import static org.apache.solr.core.PluginInfo.APPENDS;
import static org.apache.solr.core.PluginInfo.DEFAULTS;
import static org.apache.solr.core.PluginInfo.INVARIANTS;
import static org.apache.solr.core.RequestParams.USEPARAM;
/**
* Utilities that may be of use to RequestHandlers.
*/
public class SolrPluginUtils {
/**
* Map containing all the possible purposes codes of a request as key and
* the corresponding readable purpose as value
*/
private static final Map purposes;
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
static {
Map map = new TreeMap<>();
map.put(ShardRequest.PURPOSE_PRIVATE, "PRIVATE");
map.put(ShardRequest.PURPOSE_GET_TOP_IDS, "GET_TOP_IDS");
map.put(ShardRequest.PURPOSE_REFINE_TOP_IDS, "REFINE_TOP_IDS");
map.put(ShardRequest.PURPOSE_GET_FACETS, "GET_FACETS");
map.put(ShardRequest.PURPOSE_REFINE_FACETS, "REFINE_FACETS");
map.put(ShardRequest.PURPOSE_GET_FIELDS, "GET_FIELDS");
map.put(ShardRequest.PURPOSE_GET_HIGHLIGHTS, "GET_HIGHLIGHTS");
map.put(ShardRequest.PURPOSE_GET_DEBUG, "GET_DEBUG");
map.put(ShardRequest.PURPOSE_GET_STATS, "GET_STATS");
map.put(ShardRequest.PURPOSE_GET_TERMS, "GET_TERMS");
map.put(ShardRequest.PURPOSE_GET_TOP_GROUPS, "GET_TOP_GROUPS");
map.put(ShardRequest.PURPOSE_GET_MLT_RESULTS, "GET_MLT_RESULTS");
map.put(ShardRequest.PURPOSE_REFINE_PIVOT_FACETS, "REFINE_PIVOT_FACETS");
map.put(ShardRequest.PURPOSE_SET_TERM_STATS, "SET_TERM_STATS");
map.put(ShardRequest.PURPOSE_GET_TERM_STATS, "GET_TERM_STATS");
purposes = Collections.unmodifiableMap(map);
}
private static final MapSolrParams maskUseParams = new MapSolrParams(ImmutableMap.builder()
.put(USEPARAM, "")
.build());
/**
* Set default-ish params on a SolrQueryRequest.
*
* RequestHandlers can use this method to ensure their defaults and
* overrides are visible to other components such as the response writer
*
* @param req The request whose params we are interested i
* @param defaults values to be used if no values are specified in the request params
* @param appends values to be appended to those from the request (or defaults) when dealing with multi-val params, or treated as another layer of defaults for singl-val params.
* @param invariants values which will be used instead of any request, or default values, regardless of context.
*/
public static void setDefaults(SolrQueryRequest req, SolrParams defaults, SolrParams appends, SolrParams invariants) {
setDefaults(null, req, defaults, appends, invariants);
}
public static void setDefaults(SolrRequestHandler handler, SolrQueryRequest req, SolrParams defaults,
SolrParams appends, SolrParams invariants) {
String useParams = (String) req.getContext().get(USEPARAM);
if(useParams != null) {
RequestParams rp = req.getCore().getSolrConfig().getRequestParams();
defaults = applyParamSet(rp, defaults, useParams, DEFAULTS);
appends = applyParamSet(rp, appends, useParams, APPENDS);
invariants = applyParamSet(rp, invariants, useParams, INVARIANTS);
}
useParams = req.getParams().get(USEPARAM);
if (useParams != null && !useParams.isEmpty()) {
RequestParams rp = req.getCore().getSolrConfig().getRequestParams();
// now that we have expanded the request macro useParams with the actual values
// it makes no sense to keep it visible now on.
// distrib request sends all params to the nodes down the line and
// if it sends the useParams to other nodes , they will expand them as well.
// which is not desirable. At the same time, because we send the useParams
// value as an empty string to other nodes we get the desired benefit of
// overriding the useParams specified in the requestHandler directly
req.setParams(SolrParams.wrapDefaults(maskUseParams, req.getParams()));
defaults = applyParamSet(rp, defaults, useParams, DEFAULTS);
appends = applyParamSet(rp, appends, useParams, APPENDS);
invariants = applyParamSet(rp, invariants, useParams, INVARIANTS);
}
RequestUtil.processParams(handler, req, defaults, appends, invariants);
}
private static SolrParams applyParamSet(RequestParams requestParams,
SolrParams defaults, String paramSets, String type) {
if (paramSets == null) return defaults;
List paramSetList = paramSets.indexOf(',') == -1 ? singletonList(paramSets) : StrUtils.splitSmart(paramSets, ',');
for (String name : paramSetList) {
RequestParams.VersionedParams params = requestParams.getParams(name, type);
if (params == null) return defaults;
if (type.equals(DEFAULTS)) {
defaults = SolrParams.wrapDefaults(params, defaults);
} else if (type.equals(INVARIANTS)) {
defaults = SolrParams.wrapAppended(params, defaults);
} else {
defaults = SolrParams.wrapAppended(params, defaults);
}
}
return defaults;
}
/**
* SolrIndexSearch.numDocs(Query,Query) freaks out if the filtering
* query is null, so we use this workarround.
*/
public static int numDocs(SolrIndexSearcher s, Query q, Query f)
throws IOException {
return (null == f) ? s.getDocSet(q).size() : s.numDocs(q,f);
}
private final static Pattern splitList=Pattern.compile(",| ");
/** Split a value that may contain a comma, space of bar separated list. */
public static String[] split(String value){
return splitList.split(value.trim(), 0);
}
/**
* Pre-fetch documents into the index searcher's document cache.
*
* This is an entirely optional step which you might want to perform for
* the following reasons:
*
*
*
Locates the document-retrieval costs in one spot, which helps
* detailed performance measurement
*
*
Determines a priori what fields will be needed to be fetched by
* various subtasks, like response writing and highlighting. This
* minimizes the chance that many needed fields will be loaded lazily.
* (it is more efficient to load all the field we require normally).
*
*
* If lazy field loading is disabled, this method does nothing.
*/
public static void optimizePreFetchDocs(ResponseBuilder rb,
DocList docs,
Query query,
SolrQueryRequest req,
SolrQueryResponse res) throws IOException {
SolrIndexSearcher searcher = req.getSearcher();
if(!searcher.getDocFetcher().isLazyFieldLoadingEnabled()) {
// nothing to do
return;
}
ReturnFields returnFields = res.getReturnFields();
if(returnFields.getLuceneFieldNames() != null) {
Set fieldFilter = returnFields.getLuceneFieldNames();
if (rb.doHighlights) {
// copy return fields list
fieldFilter = new HashSet<>(fieldFilter);
// add highlight fields
SolrHighlighter highlighter = HighlightComponent.getHighlighter(req.getCore());
for (String field: highlighter.getHighlightFields(query, req, null))
fieldFilter.add(field);
// fetch unique key if one exists.
SchemaField keyField = searcher.getSchema().getUniqueKeyField();
if(null != keyField)
fieldFilter.add(keyField.getName());
}
// get documents
DocIterator iter = docs.iterator();
for (int i=0; i getDebugInterests(String[] params, ResponseBuilder rb){
Set debugInterests = new HashSet<>();
if (params != null) {
for (int i = 0; i < params.length; i++) {
if (params[i].equalsIgnoreCase("all") || params[i].equalsIgnoreCase("true")){
rb.setDebug(true);
break;
//still might add others
} else if (params[i].equals(CommonParams.TIMING)){
rb.setDebugTimings(true);
} else if (params[i].equals(CommonParams.QUERY)){
rb.setDebugQuery(true);
} else if (params[i].equals(CommonParams.RESULTS)){
rb.setDebugResults(true);
} else if (params[i].equals(CommonParams.TRACK)){
rb.setDebugTrack(true);
}
}
}
return debugInterests;
}
/**
*
* Returns a NamedList containing many "standard" pieces of debugging
* information.
*
*
*
*
rawquerystring - the 'q' param exactly as specified by the client
*
*
querystring - the 'q' param after any preprocessing done by the plugin
*
*
parsedquery - the main query executed formated by the Solr
* QueryParsing utils class (which knows about field types)
*
*
parsedquery_toString - the main query executed formatted by its
* own toString method (in case it has internal state Solr
* doesn't know about)
*
*
explain - the list of score explanations for each document in
* results against query.
*
*
otherQuery - the query string specified in 'explainOther' query param.
*
*
explainOther - the list of score explanations for each document in
* results against 'otherQuery'
*
*
*
* @param req the request we are dealing with
* @param userQuery the users query as a string, after any basic
* preprocessing has been done
* @param query the query built from the userQuery
* (and perhaps other clauses) that identifies the main
* result set of the response.
* @param results the main result set of the response
* @return The debug info
* @throws java.io.IOException if there was an IO error
*/
public static NamedList doStandardDebug(
SolrQueryRequest req,
String userQuery,
Query query,
DocList results,
boolean dbgQuery,
boolean dbgResults)
throws IOException
{
NamedList dbg = new SimpleOrderedMap();
doStandardQueryDebug(req, userQuery, query, dbgQuery, dbg);
doStandardResultsDebug(req, query, results, dbgResults, dbg);
return dbg;
}
public static void doStandardQueryDebug(
SolrQueryRequest req,
String userQuery,
Query query,
boolean dbgQuery,
NamedList dbg)
{
if (dbgQuery) {
/* userQuery may have been pre-processed .. expose that */
dbg.add("rawquerystring", req.getParams().get(CommonParams.Q));
dbg.add("querystring", userQuery);
/* QueryParsing.toString isn't perfect, use it to see converted
* values, use regular toString to see any attributes of the
* underlying Query it may have missed.
*/
dbg.add("parsedquery", QueryParsing.toString(query, req.getSchema()));
dbg.add("parsedquery_toString", query.toString());
}
}
public static void doStandardResultsDebug(
SolrQueryRequest req,
Query query,
DocList results,
boolean dbgResults,
NamedList dbg) throws IOException
{
if (dbgResults) {
SolrIndexSearcher searcher = req.getSearcher();
IndexSchema schema = searcher.getSchema();
boolean explainStruct = req.getParams().getBool(CommonParams.EXPLAIN_STRUCT, false);
if (results != null) {
NamedList explain = getExplanations(query, results, searcher, schema);
dbg.add("explain", explainStruct
? explanationsToNamedLists(explain)
: explanationsToStrings(explain));
}
String otherQueryS = req.getParams().get(CommonParams.EXPLAIN_OTHER);
if (otherQueryS != null && otherQueryS.length() > 0) {
DocList otherResults = doSimpleQuery(otherQueryS, req, 0, 10);
dbg.add("otherQuery", otherQueryS);
NamedList explainO = getExplanations(query, otherResults, searcher, schema);
dbg.add("explainOther", explainStruct
? explanationsToNamedLists(explainO)
: explanationsToStrings(explainO));
}
}
}
public static NamedList