Package zh.solr.se.searcher.solr

Source Code of zh.solr.se.searcher.solr.SolrUtil

package zh.solr.se.searcher.solr;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrQueryResponse;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.search.DocIterator;
import org.apache.solr.search.DocSlice;
import org.apache.solr.search.SolrIndexSearcher;

import zh.solr.se.searcher.relevance.DocSliceResult;
import zh.solr.se.searcher.relevance.ScoredSolrDoc;
import zh.solr.se.searcher.relevance.SearchResult;
import zh.solr.se.searcher.util.ConfigFactory;
import zh.solr.se.searcher.util.ConfigProperties;
import zh.solr.se.searcher.util.StringUtil;


public class SolrUtil {
  public static final String CORE_NAME_CHINESE = "core-chinese";

  public static final String INDEX_FIELD_MARKETING_TAG = "marketing_tag";
  // shared parameters
  public static final String PARAM_NAME_QUERY_TYPE   = "qt";
  public static final String PARAM_NAME_QUERY        = "q";
  public static final String PARAM_NAME_FILTER_QUERY = "fq";
  public static final String PARAM_NAME_FIELD_LIST   = "fl";

  // local search parameters
  public static final String PARAM_NAME_LOCATION   = "location";
  public static final String PARAM_NAME_LATITUDE   = "lat";
  public static final String PARAM_NAME_LONGITUDE  = "long";
  public static final String PARAM_NAME_RADIUS     = "radius";
  public static final String PARAM_NAME_ROWS       = "rows";

  // geoip search parameters
  public static final String PARAM_NAME_IP  =  "ip";
  public static final String PARAM_NAME_MODE  =  "mode";

  // local search parameters
  public static final String PARAM_NAME_DEBUG = "debug";

  // choose the algorithm
  public static final String PARAM_NAME_RELEVANCE_ALGORITHM = "relevance_algorithm";

  // Solr response field names
  public static final String SOLR_NAME_RESPONSE_HEADER = "responseHeader";
  public static final String SOLR_NAME_RESPONSE_PARAMS = "params";
  public static final String SOLR_NAME_RESPONSE_RESULT = "response";
  public static final String SOLR_NAME_RESPONSE_DOCS   = "docs";
 
  public static final String SOLR_NAME_FACET_COUNTS   = "facet_counts";
  public static final String SOLR_NAME_FACET_FIELDS   = "facet_fields";
  public static final String SOLR_NAME_FACET_QUERIES   = "facet_queries";
 
 
  public static final String SOLR_NAME_RESPONE_SOLR_SERVER_HOSTNAME = "solr_server_hostname";

  // parameter values
  public static final String PARAM_VALUE_SCORE      = "score";
  public static final String PARAM_VALUE_TRUE       = "true";
  public static final String PARAM_VALUE_ALGORITHM_EXACT = "exact_match";
 

  public static int getRows(SolrParams queryParams) {
    ConfigProperties searchProperties = ConfigFactory.getInstance().getConfigProperties(ConfigFactory.SEARCH_CONFIG_PATH);
    int defaultRows = searchProperties.getInt(ConfigProperties.CONFIG_NAME_DEFAULT_ROWS, SearchResult.DEFAULT_PAGE_SIZE);
    int rows = queryParams.getInt(SolrUtil.PARAM_NAME_ROWS, defaultRows);

    return rows;
  }

  /**
   * Add/modify/Remove a single parameter in the Solr request
   * @param solrReq the Solr request
   * @param name is the name of the parameter
   * @param value is the parameter value to set. It will be removed from the parameter list if the value is null
   */
  public static void setSolrRequestParam(SolrQueryRequest solrReq, String name, Object value) {
    HashMap<String, Object> valueMap = new HashMap<String, Object>();
    valueMap.put(name, value);
    setSolrRequestParams(solrReq, valueMap);
  }

  /**
   * Add/modify/Remove multiple parameters in the Solr request
   * @param solrReq the Solr request
   * @param valueMap a list of parameter name and value. A parameter will be removed if its value is null
   */
  public static void setSolrRequestParams(SolrQueryRequest solrReq, Map<String, Object> valueMap) {
    if (valueMap == null)
      return;

    NamedList<Object> paramList = solrReq.getParams().toNamedList();
    for (String name : valueMap.keySet()) {
      setNamedListEntry(paramList, name, valueMap.get(name));
    }

    // create the new Solr request params and set it back to the request
    SolrParams params = SolrParams.toSolrParams(paramList);
    solrReq.setParams(params);
  }

  public static void setResponseHeaderParam(SolrQueryResponse solrResp, String name, Object value) {
    HashMap<String, Object> paramMap = new HashMap<String, Object>();
    paramMap.put(name, value);
    setResponseHeaderParams(solrResp, paramMap);
  }

  public static void setResponseHeaderParams(SolrQueryResponse solrResp, Map<String, Object> paramMap) {
    if (solrResp == null || paramMap == null)
      return;

    NamedList responseValues = solrResp.getValues();
    NamedList header = (NamedList)responseValues.get(SOLR_NAME_RESPONSE_HEADER);
    if(header == null) {
      return;
    }

    NamedList headerParams = (NamedList)header.get(SOLR_NAME_RESPONSE_PARAMS);

    // update the parameters
    for (String name : paramMap.keySet()) {
      setNamedListEntry(headerParams, name, paramMap.get(name));
    }
  }

  public static void clearSolrResponse(SolrQueryResponse solrResp) {
    if (solrResp == null)
      return;

    NamedList responseValues = solrResp.getValues();
    if (responseValues == null)
      return;

    // remove the header
    setNamedListEntry(responseValues, SolrUtil.SOLR_NAME_RESPONSE_HEADER, null);

    // remove the search result
    setNamedListEntry(responseValues, SolrUtil.SOLR_NAME_RESPONSE_RESULT, null);
  }

  public DocSlice mergeSearchResultList(List<DocSlice> searchResultList) {
    return mergeSearchResultList(searchResultList, -1);
  }

  /**
   * Merge two search results into one
   *
   * @param result1
   * @param result2
   * @param maxCount the max docs we need in the merged search result
   * @return
   */
  public static DocSlice mergeTwoSearchResults(DocSlice result1, DocSlice result2, int maxCount) {
    if (result1 == null)
      return result2;

    if (result2 == null)
      return result1;

    ArrayList<DocSlice> resultList = new ArrayList<DocSlice>();
    resultList.add(result1);
    resultList.add(result2);

    return mergeSearchResultList(resultList, maxCount);
  }

  /**
   * Merge a list of DocSlice objects into one
   * @param searchResultList
   * @param maxCount the max docs we need in the merge search result
   * @return
   */
  public static DocSlice mergeSearchResultList(List<DocSlice> searchResultList, int maxCount) {
    if (searchResultList == null || searchResultList.size() == 0)
      return null;

    // if there is a valid max count, then cut the result to it if necessary
    int length = getTotalCount(searchResultList);
    if (maxCount > 0 && length > maxCount)
      length = maxCount;

    int[] docList = new int[length];
    float[] scoreList = new float[length];
    int count = 0;
    float maxScore = 0.0f;
    for (DocSlice searchResult : searchResultList) {
      if (searchResult == null)
        continue;

      // append the docs in the search result to the doc list
      count = appendDocs(searchResult, count, docList, scoreList, maxCount);

      // max score among all search results
      if (searchResult.hasScores()) {
        float tempMax = searchResult.maxScore();
        if (tempMax > maxScore)
          maxScore = tempMax;
      }

      if (maxCount > 0 && count >= maxCount)
        break;
    }

    // the difference between count and length is the number of duplicates
    int duplicates = length - count;

    int totalMatches = getTotalMatches(searchResultList) - duplicates;

    return new DocSlice(0, count, docList, scoreList, totalMatches, maxScore);
  }

  public static DocSlice cutoffLowScores(DocSlice searchResult, float cutoffScore) {
    if (searchResult == null || searchResult.size() <= 0 || !searchResult.hasScores() || cutoffScore <= 0)
      return searchResult;

    int length = searchResult.size();

    int[] docList = new int[length];
    float[] scoreList = new float[length];
    float maxScore = searchResult.maxScore();
    int matches = searchResult.matches();
    int count = 0;
    DocIterator iterator = searchResult.iterator();
    while (iterator.hasNext()) {
      int docId = iterator.nextDoc();
      float score = iterator.score();
      if (score >= cutoffScore) {
        // keep the search result only if its score is equal to or above the cutoff score
        docList[count] = docId;
        scoreList[count] = score;
        count++;
      }
    }

    if (count < length) {
      // if we already cut some from the first page, then total match should be what we keep
      matches = count;
    }

    return new DocSlice(0, count, docList, scoreList, matches, maxScore);
  }

  /**
   * add/modify/remove the entries of a NamedList. See the method of setNamedLitEntry
   * @param list
   * @param valueMap
   */
  public static void setNamedListEntries(NamedList list, Map<String, Object> valueMap) {
    if (list == null || valueMap == null)
      return;

    for (String name : valueMap.keySet()) {
      setNamedListEntry(list, name, valueMap.get(name));
    }
  }

  /**
   * Add/modify/remove an entry of a named list. Add if the entry does not exist,
   * modify if the entry exists, remove if the value is null
   * @param namedList
   * @param name
   * @param value
   */
  public static void setNamedListEntry(NamedList namedList, String name, Object value) {
    assert name != null;

    if(namedList == null) {
      return;
    }

    // remove the existing value
    Object existingValue = namedList.get(name);
    if (existingValue != null) {
      //namedList.remove(name);
      int idx = namedList.indexOf(name, 0);
      if (idx >= 0) {
          namedList.remove(idx);
      }
    }

    // add the value
    if (value != null)
      namedList.add(name, value);
  }

  /**
   * Get the total document count of the search result list.
   * This is different from the total matches.
   *
   * @param searchResultList
   * @return
   */
  public static int getTotalCount(List<DocSlice> searchResultList) {
    if (searchResultList == null)
      return 0;

    int totalCount = 0;
    for (DocSlice searchResult : searchResultList) {
      totalCount += searchResult.size();
    }

    return totalCount;
  }

  /**
   * Get the total matches of the search result list
   *
   * @param searchResultList
   * @return
   */
  public static int getTotalMatches(List<DocSlice> searchResultList) {
    if (searchResultList == null)
      return 0;

    int totalMatches = 0;
    for (DocSlice searchResult : searchResultList) {
      totalMatches += searchResult.matches();
    }

    return totalMatches;

  }

  /**
   * Construct the search query against multiple fields with different boosts
   *
   * @param keyword the keyword to search for
   * @param fieldsAndBoosts a list of field to search against and corresponding field boosts
   * @return
   */
  public static String constructQuery(String keyword, Map<String, Float> fieldsAndBoosts) {
    assert keyword != null;

    // we search the keywords against 3 fields, question_keyword,
    // question_tags, question with different boosts as configured
    StringBuilder queryBuilder = new StringBuilder("(");
    boolean firstField = true;
    for (String fieldName : fieldsAndBoosts.keySet()) {
      if (firstField)
        firstField = false;
      else
        queryBuilder.append(" OR ");
      queryBuilder.append(fieldName).append(":")
        .append("(").append(keyword).append(")^").append(fieldsAndBoosts.get(fieldName));
    }
    queryBuilder.append(")");

    return queryBuilder.toString();
  }

  /*
   * Replace missing query with "q = *:*". Standard request handler would throw
   * a NullPointerException if q is missing
   *
   * @param solrReq
   */
  public static void fixMissingQuery(SolrQueryRequest solrReq) {
    String query = solrReq.getParams().get(SolrUtil.PARAM_NAME_QUERY);
    if (query == null || query.length() == 0)
      SolrUtil.setSolrRequestParam(solrReq, SolrUtil.PARAM_NAME_QUERY, "*:*");
  }

  /**
   * Make sure the score field is included in the field list parameter
   * @param solrReq the solr request to which we update the field list parameter
   */
  public static void includeScoreInFieldList(SolrQueryRequest solrReq) {
    if (solrReq == null)
      return;

    String fieldList = solrReq.getParams().get(PARAM_NAME_FIELD_LIST);
    if (fieldList == null || fieldList.trim().length() == 0) {
      // the client did not specify field list, return all plus score
      fieldList = "*," + PARAM_VALUE_SCORE;
    } else if (fieldList.indexOf(PARAM_VALUE_SCORE) < 0){
      // the client specified a field list, but did not ask for score. add score to the list
      fieldList = fieldList + "," + PARAM_VALUE_SCORE;
    }

    // set the field list to the Solr request
    setSolrRequestParam(solrReq, PARAM_NAME_FIELD_LIST, fieldList);
  }

  /**
   * Make sure the score and primary key field are included in the field list parameter
   * @param solrReq the solr request to which we update the field list parameter
   */
  public static void includeScoreAndKeyInFieldList(SolrQueryRequest solrReq, String uniqueKey) {
    if (solrReq == null)
      return;

    String fieldList = solrReq.getParams().get(PARAM_NAME_FIELD_LIST);
    if (fieldList == null || fieldList.trim().length() == 0) {
      // the client did not specify field list, return all plus score
      fieldList = "*," + PARAM_VALUE_SCORE;
    } else {
      if (fieldList.indexOf(uniqueKey) < 0){
        // the client specified a field list, but did not ask for key. add key to the list
        fieldList = fieldList + "," + uniqueKey;
      }

      if (fieldList.indexOf(PARAM_VALUE_SCORE) < 0){
        // the client specified a field list, but did not ask for score. add score to the list
        fieldList = fieldList + "," + PARAM_VALUE_SCORE;
      }
    }

    // set the field list to the Solr request
    setSolrRequestParam(solrReq, PARAM_NAME_FIELD_LIST, fieldList);
  }

  /**
   * Check if the keyword is missing, or just white spaces, or just a parentheses
   * @param keyword the keyword to check
   * @return true if the keyword is empty
   */
  public static boolean emptyKeyword(String keyword) {
    if (keyword == null)
      return true;

    keyword = keyword.trim();
    if (keyword.length() == 0)
      return true;

    // take off the opening and closing parenthesis
    if (keyword.startsWith("("))
      keyword = keyword.substring(1);
    if (keyword.endsWith(")"))
      keyword = keyword.substring(0, keyword.length() - 1);

    if (keyword.trim().length() == 0)
      return true;

    return false;
  }

  /**
   * create a Solr query string in the form of "field:(value)^boost"
   * @param fieldName
   * @param fieldValue
   * @param boost
   * @return Solr field query
   */
  public static String createFeildQuery(String fieldName, String fieldValue, float boost) {
    if (fieldName == null || fieldValue == null)
      return null;

    // escape the special characters in the field value
    fieldValue = QueryParser.escape(fieldValue);

    if (boost < 0)
      boost = 1.0f;

    StringBuilder queryBuilder = new StringBuilder();
    queryBuilder.append(fieldName).append(":(").append(fieldValue).append(")^").append(boost);

    return queryBuilder.toString();
  }

  /**
   * create a Solr query string in the form of "field:"keyword"^boost"
   * @param fieldName
   * @param fieldValue
   * @param boost
   * @return Solr field query
   */
  public static String createExactMatchQuery(String fieldName, String fieldValue, float boost) {
    if (fieldName == null || fieldValue == null)
      return null;

    // escape the special characters in the field value
    fieldValue = QueryParser.escape(fieldValue);

    StringBuilder queryBuilder = new StringBuilder();
    queryBuilder.append(fieldName).append(":\"").append(fieldValue).append("\"");
    if (boost >= 0)
      queryBuilder.append("^").append(boost);

    return queryBuilder.toString();
  }

  /**
   * For each document in the search result, retrieve the specified field values and populate the document with the values.
   * @param searchResult
   * @param searcher the solr index searcher for retrieving the field values
   * @param fieldSet specifies the desired fields and whether they are mutliple valued.
   */
  public static void populateFields(
      SearchResult searchResult, SolrIndexSearcher searcher, Set<String> fieldSet)
  {
    if (searchResult == null || searcher == null || fieldSet == null)
      return;

    for (ScoredSolrDoc doc : ((DocSliceResult)searchResult)) {
      doc.setFieldValueMap(retrieveFieldValues(searcher, doc.getDocId(), fieldSet));
    }
  }

  /**
   * Retrieve the field values from a Solr document. The value is always a string.
   * If there are multiple values, values will be put together as single string using the pre-defined separator.
   *
   * @param searcher the Solr searcher
   * @param docId document ID of the document to retrieve field values from
   * @param fieldNameSet a list of field names whose values are to be retrieved
   * @return a map of field names and field values
   */
  public static Map<String, String> retrieveFieldValues(
      SolrIndexSearcher searcher, int docId, Set<String> fieldNameSet)
  {
    assert searcher != null;
    if (fieldNameSet == null || fieldNameSet.size() == 0)
      return null;

    IndexSchema schema = searcher.getSchema();

    HashMap<String, String> fieldValueMap = new HashMap<String, String>();
    try {
      Document solrDoc = searcher.doc(docId, fieldNameSet);
      for (String fieldName : fieldNameSet) {
        String fieldValue = null;
        FieldType fieldType = schema.getField(fieldName).getType();

        // the following code is to make sure it works for sortable numerical fields
        if (fieldType.isMultiValued()) {
          // concatenate all the values for multi-valued field
          Fieldable[] fields = solrDoc.getFieldables(fieldName);
          if (fields != null && fields.length > 0) {
            ArrayList<String> valueList = new ArrayList<String>();
            for (Fieldable fd : fields) {
              Object fieldObj = fieldType.toObject(fd);
              if (fieldObj != null)
                valueList.add(fieldObj.toString());
            }
            fieldValue = StringUtil.listToString(valueList, ",");
          }

        } else {
          // single valued field
          Fieldable field = solrDoc.getFieldable(fieldName);
          if (field != null) {
            Object fieldObj = fieldType.toObject(field);
            if (fieldObj != null)
              fieldValue = fieldObj.toString();
          }
        }

        if (fieldValue != null)
          fieldValueMap.put(fieldName, fieldValue.toString());
      }
    } catch (Exception e) {
      e.printStackTrace();
    }

    return fieldValueMap;
  }

  /**
   * Get the value of the specified Solr request parameter
   * @param solrReq the Solr request object from which to retrieve the parameter
   * @param paramName the name of the requested parameter
   * @return the value of the parameter
   */
  public static String getSolrRequestParameter(SolrQueryRequest solrReq, String paramName) {
    if (solrReq == null || paramName == null)
      return null;

    SolrParams params = solrReq.getParams();
    if (params == null)
      return null;

    return params.get(paramName);
  }

  /**
   * Combine two Solr queries
   * @param query1
   * @param query2
   * @return the combined query string
   */
  public static String combineTwoQueries(String query1, String query2) {
    if (query1 == null)
      return query2;
    else if (query2 == null)
      return query1;
    else
      return "(" + query1 + " OR " + query2 + ")";
  }

  private static int appendDocs(DocSlice searchResult, int offset, int[] docList, float[] scoreList, int maxCount) {
    boolean hasScores = searchResult.hasScores();
    DocIterator iterator = searchResult.iterator();
    int count = offset;

    while (iterator.hasNext() && (maxCount <= 0 || count < maxCount)) {
      int docId = iterator.nextDoc();

      // don't add any duplicate documents
      if (docExists(docId, docList))
        continue;

      // add the doc to the total doc list
      docList[count] = docId;
      if (hasScores) {
        scoreList[count] = iterator.score();
      }
      count++;
    }

    return count;
  }

  private static boolean docExists(int docId, int[] docList) {
    // the assumption is the list is not too large, typically less than 10

    for (int existingId : docList) {
      if (docId == existingId)
        return true;
    }

    return false;
  }

  public static void printNamedList(NamedList<Object> valueList, String marker) {
    System.out.println("====================== " + marker + " Begins ====================== ");
    Iterator<Map.Entry<String, Object>> valueIterator = valueList.iterator();
    while (valueIterator.hasNext()) {
      Map.Entry<String, Object> entry = valueIterator.next();
      String name = entry.getKey();
      Object value = entry.getValue();
      System.out.println("name = " + name + ", value = " + value + ", type = " + value.getClass().getSimpleName());
    }
    System.out.println("====================== " + marker + " Ends ====================== ");
  }
 
  public static String getLocalIp() {
    String localIP = null;
    Enumeration<NetworkInterface> netInterfaces = null;
    try {
      netInterfaces = NetworkInterface.getNetworkInterfaces();
      while (netInterfaces.hasMoreElements()) {
        NetworkInterface ni = netInterfaces.nextElement();
        if (null != ni) {
          Enumeration<InetAddress> ips = ni.getInetAddresses();
          while (ips.hasMoreElements()) {
            localIP = ips.nextElement().getHostAddress();
            if (localIP.startsWith("10.")) {
              return localIP;
            }
          }
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return localIP;
  }
 
  public static String getHostName() {
    String hostname = null;
    try {
      InetAddress add = InetAddress.getLocalHost();
      hostname = add.getHostName();
    } catch (UnknownHostException e) {
      e.printStackTrace();
    }
    return hostname;
  }

  public static void main(String[] args) {
  }
}
TOP

Related Classes of zh.solr.se.searcher.solr.SolrUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.