Package zh.solr.se.searcher.relevance

Source Code of zh.solr.se.searcher.relevance.DocSliceResult

package zh.solr.se.searcher.relevance;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Set;

import org.apache.solr.search.DocIterator;
import org.apache.solr.search.DocSlice;
import org.apache.solr.search.SolrIndexSearcher;

import zh.solr.se.searcher.solr.SolrUtil;

public class DocSliceResult extends ArrayList<ScoredSolrDoc> implements SearchResult
  private int matches = 0;

  /**
   * construct an empty SearchResult object
   */
  public DocSliceResult() {
  }
 
  /**
   * Construct a SearchResult object from a DocSlice object
   * @param docSlice the DocSlice object
   */
  public DocSliceResult(DocSlice docSlice) {
    this(docSlice, null, null);
  }
 
  /**
   * Construct a SearchResult object from a DocSlice object
   * @param docSlice the DocSlice object
   * @param searcher Solr index searcher
   * @param fieldSet the desired field names and whether they multi-valued
   */
  public DocSliceResult(DocSlice docSlice, SolrIndexSearcher searcher, Set<String> fieldSet) {
    if (docSlice == null)
      throw new NullPointerException("The DocSlice object for constructing search result must not be null");
   
    if (fieldSet != null && searcher == null) {
      throw new NullPointerException("Searcher must not be null to retieve field values");
    }
   
    // get the matches
    this.setMatches(docSlice.matches());
   
    // retrieve all the documents
    DocIterator iterator = docSlice.iterator();
    while (iterator.hasNext()) {
      int docId = iterator.nextDoc();
      float score = 1.0f;     
      if (docSlice.hasScores())
        score = iterator.score();
     
      ScoredSolrDoc doc = new ScoredSolrDoc(docId, score);
     
      // retrieve requested field values
      if (fieldSet != null) {
        Map<String, String> valueMap = SolrUtil.retrieveFieldValues(searcher, docId, fieldSet);
        doc.setFieldValueMap(valueMap);
      }
     
      this.add(doc);
    }
  }
 
  public void addDoc(Object doc) {
    if (doc == null)
      return;
   
    super.add((ScoredSolrDoc)doc);
    matches++;
  }
 
  /**
   * Sort the doc list by score from high to low, and only return the specified number of docs
   * @param maxCount max number of docs to return
   */
  public void sortByScore(int maxCount) {
    if (this.size() < 2)
      return;
   
    // creating the comparator that compares doc scores from high to low
    Comparator<ScoredSolrDoc> comparator = new Comparator<ScoredSolrDoc>() {
      public int compare(ScoredSolrDoc doc1, ScoredSolrDoc doc2) {
        return (int)Math.signum(doc2.getScore() - doc1.getScore());
      }
    };
   
    if (maxCount <= 0 || maxCount >= this.size()) {
      // full sorting
      Collections.sort(this, comparator);
    } else {
      // use priority queue for partial sorting
      PriorityQueue<ScoredSolrDoc> docQueue = new PriorityQueue<ScoredSolrDoc>(maxCount, comparator);
      for (ScoredSolrDoc doc : this) {
        docQueue.add(doc);
      }
     
      // replace the original list with the items in the queue
      this.clear();
      for (int i = 0; i < maxCount; i++) {
        this.add(docQueue.poll());
      }
    }
  }
 
  /**
   * Convert to a DocSlice object
   */
  public DocSlice toSolrSearchResult() {
    int length = size();
    int[] idList = new int[length];
    float[] scoreList = new float[length];
    float maxScore = 0f;
    for (int i = 0; i < length; i++) {
      ScoredSolrDoc solrDoc = get(i);
      idList[i] = solrDoc.getDocId();
      scoreList[i] = solrDoc.getScore();
      if (scoreList[i] > maxScore)
        maxScore = scoreList[i];
    }
   
    return new DocSlice(0, length, idList, scoreList, matches, maxScore);
  }
 
  public SearchResult merge(SearchResult result1, SearchResult result2, int maxCount) {
    if (maxCount <= 0)
      maxCount = DEFAULT_PAGE_SIZE;
   
    if (result1 == null)
      return result2;
    else if (result2 == null || ((DocSliceResult)result1).size() >= maxCount)
      return result1;
       
    DocSliceResult mergedResult = new DocSliceResult();
   
    // append the first result to the merged result
    mergedResult.addAll((DocSliceResult)result1);
   
    // append the second result to the merged result, excluding any duplicates
    HashSet<Object> docIdHashSet = result1.getDocIdHashSet();
    int duplicates = 0;
    for (int i = 0; (i < ((DocSliceResult)result2).size() && mergedResult.size() <= maxCount); i++) {
      ScoredSolrDoc doc = ((DocSliceResult)result2).get(i);
      if (docIdHashSet.contains(doc.getDocId())) {
        duplicates++;
      } else {
        mergedResult.add(doc);
        docIdHashSet.add(doc.getDocId());
      }
    }
   
    // exclude the duplicates from the total matches
    int totalMatches = result1.getMatches() + result2.getMatches() - duplicates;
    mergedResult.setMatches(totalMatches);
   
    return mergedResult;
  }

  public void mergeWith(SearchResult anotherResult, int maxCount) {
    if (anotherResult == null || ((DocSliceResult)anotherResult).size() == 0)
      return;
   
    if (maxCount <= 0)
      maxCount = DEFAULT_PAGE_SIZE;
   
    int totalMatches = this.getMatches() + anotherResult.getMatches();
    if (maxCount <= this.size()) {
      // we need to cut the current result, and we don't need the second result.
      this.removeRange(maxCount, this.size());
    } else {
      // append needed docs
      HashSet<Object> docIdHashSet = this.getDocIdHashSet();
      int duplicates = 0;
      for (int i = 0; (i < ((DocSliceResult)anotherResult).size() && this.size() <= maxCount); i++) {
        ScoredSolrDoc doc = ((DocSliceResult)anotherResult).get(i);
        if (docIdHashSet.contains(doc.getDocId())) {
          duplicates++;
        } else {
          this.add(doc);
          docIdHashSet.add(doc.getDocId());
        }
      }
     
      // remove the duplicates from the total matches
      totalMatches -= duplicates;
    }
   
    setMatches(totalMatches);
  }
 
  public void scaleScores(float scaleFactor) {
    if (scaleFactor < 0)
      return;
    for (ScoredSolrDoc doc : this) {
      doc.setScore(doc.getScore() * scaleFactor);
    }
  }
 
  public void discardLowScoreResults(float threshold) {
    // cut from the end, so that the earlier index does not change after the cut
    // please note that the scores don't necessarily in any order
    int origSize = this.size();
    for (int i = origSize - 1; i >= 0; i--) {
      if (this.get(i).getScore() < threshold) {
        this.remove(i);
      }
    }
   
    // if any of the search result on the first page is removed, then the rest on later pages
    // should be removed too. We should update the matches to what are left on the first page
    if (this.size() < origSize)
      setMatches(this.size());
  }
 
  public int getMatches() {
    return matches;
  }

  public void setMatches(int matches) {
    this.matches = matches;
  }

  public Float getMaxScore() {
    float maxScore = 0f;
    for (ScoredSolrDoc doc : this) {
      float tempScore = doc.getScore();
      if (tempScore > maxScore)
        maxScore = tempScore;
    }
   
    return maxScore;
  }
 
  public HashSet<Object> getDocIdHashSet() {
    HashSet<Object> idSet = new HashSet<Object>();
    for (ScoredSolrDoc doc : this) {
      idSet.add(doc.getDocId());
    }
   
    return idSet;
  }
 
  public void removeRange (int fromIndex, int toIndex) {
    super.removeRange(fromIndex, toIndex);
  }

}
TOP

Related Classes of zh.solr.se.searcher.relevance.DocSliceResult

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.