All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.browseengine.bobo.api.MultiBoboBrowser Maven / Gradle / Ivy

Go to download

Bobo is a Faceted Search implementation written purely in Java, an extension of Apache Lucene

The newest version!
package com.browseengine.bobo.api;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.log4j.Logger;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.MultiReader;
import org.apache.lucene.search.Collector;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.similarities.Similarity;

import com.browseengine.bobo.facets.FacetHandler;
import com.browseengine.bobo.sort.SortCollector;

/**
 * Provides implementation of Browser for multiple Browser instances
 */
public class MultiBoboBrowser extends MultiReader implements Browsable {
  private static Logger logger = Logger.getLogger(MultiBoboBrowser.class);

  protected final Browsable[] _subBrowsers;

  /**
   *
   * @param browsers
   *          Browsers to search on
   * @throws IOException
   */
  public MultiBoboBrowser(Browsable[] browsers) throws IOException {
    super(getSegmentReaders(browsers), false);
    _subBrowsers = browsers;
  }

  private static IndexReader[] getSegmentReaders(Browsable[] browsers) {
    IndexReader[] readers = new IndexReader[browsers.length];
    for (int i = 0; i < browsers.length; ++i) {
      readers[i] = browsers[i].getIndexReader();
    }
    return readers;
  }

  @Override
  public void browse(BrowseRequest req, final Collector hc, Map facetMap,
      int start) throws BrowseException {
    // index empty
    if (_subBrowsers == null || _subBrowsers.length == 0) {
      return;
    }

    try {
      Query q = req.getQuery();
      MatchAllDocsQuery matchAllDocsQuery = new MatchAllDocsQuery();
      if (q == null) {
        q = matchAllDocsQuery;
      } else if (!(q instanceof MatchAllDocsQuery)) {
        // MatchAllQuery is needed to filter out the deleted docids, that reside in
        // ZoieSegmentReader and are not visible on Bobo level
        matchAllDocsQuery.setBoost(0f);
        q = QueriesSupport.combineAnd(matchAllDocsQuery, q);
      }
      req.setQuery(q);
    } catch (Exception ioe) {
      throw new BrowseException(ioe.getMessage(), ioe);
    }

    Map> mergedMap = new HashMap>();
    try {
      Map facetColMap = new HashMap();
      for (int i = 0; i < _subBrowsers.length; i++) {
        try {
          _subBrowsers[i].browse(req, hc, facetColMap, (start + readerBase(i)));
        } finally {
          Set> entries = facetColMap.entrySet();
          for (Entry entry : entries) {
            String name = entry.getKey();
            FacetAccessible facetAccessor = entry.getValue();
            List list = mergedMap.get(name);
            if (list == null) {
              list = new ArrayList(_subBrowsers.length);
              mergedMap.put(name, list);
            }
            list.add(facetAccessor);
          }
          facetColMap.clear();
        }
      }
    } finally {
      if (req.getMapReduceWrapper() != null) {
        req.getMapReduceWrapper().finalizePartition();
      }
      Set>> entries = mergedMap.entrySet();
      for (Entry> entry : entries) {
        String name = entry.getKey();
        FacetHandler handler = getFacetHandler(name);
        try {
          List subList = entry.getValue();
          if (subList != null) {
            FacetAccessible merged = handler.merge(req.getFacetSpec(name), subList);
            facetMap.put(name, merged);
          }
        } catch (Exception e) {
          logger.error(e.getMessage(), e);
        }
      }
    }
  }

  /**
   * Generate a merged BrowseResult from the given BrowseRequest
   * @param req
   *          BrowseRequest for generating the facets
   * @return BrowseResult of the results of the BrowseRequest
   */
  @Override
  public BrowseResult browse(BrowseRequest req) throws BrowseException {

    final BrowseResult result = new BrowseResult();

    // index empty
    if (_subBrowsers == null || _subBrowsers.length == 0) {
      return result;
    }
    long start = System.currentTimeMillis();
    int offset = req.getOffset();
    int count = req.getCount();

    if (offset < 0 || count < 0) {
      throw new IllegalArgumentException("both offset and count must be > 0: " + offset + "/"
          + count);
    }
    SortCollector collector = getSortCollector(req.getSort(), req.getQuery(), offset, count,
      req.isFetchStoredFields(), req.getTermVectorsToFetch(), req.getGroupBy(), req.getMaxPerGroup(),
      req.getCollectDocIdCache());

    Map facetCollectors = new HashMap();
    browse(req, collector, facetCollectors, 0);
    if (req.getMapReduceWrapper() != null) {
      result.setMapReduceResult(req.getMapReduceWrapper().getResult());
    }
    BrowseHit[] hits = null;
    try {
      hits = collector.topDocs();
    } catch (IOException e) {
      logger.error(e.getMessage(), e);
      result.addError(e.getMessage());
      hits = new BrowseHit[0];
    }

    Query q = req.getQuery();
    if (req.isShowExplanation()) {
      for (BrowseHit hit : hits) {
        try {
          int doc = hit.getDocid();
          int idx = readerIndex(doc);
          int deBasedDoc = doc - readerBase(idx);
          Explanation expl = _subBrowsers[idx].explain(q, deBasedDoc);
          hit.setExplanation(expl);
        } catch (IOException e) {
          logger.error(e.getMessage(), e);
          result.addError(e.getMessage());
        }
      }
    }

    result.setHits(hits);
    result.setNumHits(collector.getTotalHits());
    result.setNumGroups(collector.getTotalGroups());
    result.setGroupAccessibles(collector.getGroupAccessibles());
    result.setSortCollector(collector);
    result.setTotalDocs(numDocs());
    result.addAll(facetCollectors);
    long end = System.currentTimeMillis();
    result.setTime(end - start);
    // set the transaction ID to trace transactions
    result.setTid(req.getTid());
    return result;
  }

  /**
   * Return the values of a field for the given doc
   *
   */
  @Override
  public String[] getFieldVal(int docid, final String fieldname) throws IOException {
    int i = readerIndex(docid);
    Browsable browser = _subBrowsers[i];
    return browser.getFieldVal(docid - readerBase(i), fieldname);
  }

  @Override
  public Object[] getRawFieldVal(int docid, String fieldname) throws IOException {
    int i = readerIndex(docid);
    Browsable browser = _subBrowsers[i];
    return browser.getRawFieldVal(docid - readerBase(i), fieldname);
  }

  /**
   * Compare BrowseFacets by their value
   */
  public static class BrowseFacetValueComparator implements Comparator {
    @Override
    public int compare(BrowseFacet o1, BrowseFacet o2) {
      return o1.getValue().compareTo(o2.getValue());
    }
  }

  /**
   * Gets the sub-browser for a given docid
   *
   * @param docid
   * @return sub-browser instance
   */
  public Browsable subBrowser(int docid) {
    int i = readerIndex(docid);
    return _subBrowsers[i];
  }

  @Override
  public void setSimilarity(Similarity similarity) {
    for (Browsable subBrowser : _subBrowsers) {
      subBrowser.setSimilarity(similarity);
    }
  }

  @Override
  public Set getFacetNames() {
    Set names = new HashSet();
    for (Browsable subBrowser : _subBrowsers) {
      names.addAll(subBrowser.getFacetNames());
    }
    return names;
  }

  @Override
  public FacetHandler getFacetHandler(String name) {
    for (Browsable subBrowser : _subBrowsers) {
      FacetHandler subHandler = subBrowser.getFacetHandler(name);
      if (subHandler != null) return subHandler;
    }
    return null;
  }

  @Override
  public Map> getFacetHandlerMap() {
    HashMap> map = new HashMap>();
    for (Browsable subBrowser : _subBrowsers) {
      map.putAll(subBrowser.getFacetHandlerMap());
    }
    return map;
  }

  @Override
  public void setFacetHandler(FacetHandler facetHandler) throws IOException {
    for (Browsable subBrowser : _subBrowsers) {
      subBrowser.setFacetHandler(facetHandler);
    }
  }

  @Override
  public SortCollector getSortCollector(SortField[] sort, Query q, int offset, int count,
      boolean fetchStoredFields, Set termVectorsToFetch, String[] groupBy, int maxPerGroup,
      boolean collectDocIdCache) {
    if (_subBrowsers.length == 1) {
      return _subBrowsers[0].getSortCollector(sort, q, offset, count, fetchStoredFields,
        termVectorsToFetch, groupBy, maxPerGroup, collectDocIdCache);
    }
    return SortCollector.buildSortCollector(this, q, sort, offset, count, fetchStoredFields,
      termVectorsToFetch, groupBy, maxPerGroup, collectDocIdCache);
  }

  @Override
  public void doClose() throws IOException {
    super.doClose();
    for (Browsable subBrowser : _subBrowsers) {
      subBrowser.doClose();
    }
  }

  @Override
  public IndexReader getIndexReader() {
    return this;
  }

  @Override
  public Explanation explain(Query q, int deBasedDoc) throws IOException {
    throw new UnsupportedOperationException();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy