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

com.orientechnologies.lucene.engine.OLuceneFacetManager Maven / Gradle / Ivy

/*
 *
 *  * Copyright 2014 Orient Technologies.
 *  *
 *  * Licensed 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 com.orientechnologies.lucene.engine;

import com.orientechnologies.common.io.OFileUtils;
import com.orientechnologies.common.log.OLogManager;
import com.orientechnologies.lucene.query.QueryContext;
import com.orientechnologies.orient.core.db.ODatabaseDocumentInternal;
import com.orientechnologies.orient.core.index.OCompositeKey;
import com.orientechnologies.orient.core.index.OIndexEngineException;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage;
import com.orientechnologies.orient.core.storage.impl.local.paginated.OLocalPaginatedStorage;
import org.apache.lucene.document.Document;
import org.apache.lucene.facet.FacetField;
import org.apache.lucene.facet.FacetsConfig;
import org.apache.lucene.facet.taxonomy.TaxonomyWriter;
import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader;
import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.NIOFSDirectory;
import org.apache.lucene.store.RAMDirectory;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * Created by Enrico Risa on 22/04/15.
 */
public class OLuceneFacetManager {

  public static final    String FACET_FIELDS = "facetFields";
  protected static final String FACET        = "_facet";
  protected TaxonomyWriter taxonomyWriter;
  protected FacetsConfig config = new FacetsConfig();
  protected String                     facetField;
  // protected String facetDim;
  private   OLuceneIndexEngineAbstract owner;
  private   ODocument                  metadata;

  public OLuceneFacetManager(OLuceneIndexEngineAbstract owner, ODocument metadata) throws IOException {
    this.owner = owner;

    this.metadata = metadata;
    buildFacetIndexIfNeeded();
  }

  protected void buildFacetIndexIfNeeded() throws IOException {

    if (metadata != null && metadata.containsField(FACET_FIELDS)) {
      ODatabaseDocumentInternal database = owner.getDatabase();
      Iterable iterable = metadata.field(FACET_FIELDS);
      if (iterable != null) {
        Directory dir = getTaxDirectory(database);
        taxonomyWriter = new DirectoryTaxonomyWriter(dir, IndexWriterConfig.OpenMode.CREATE_OR_APPEND);
        for (String s : iterable) {
          facetField = s;
          // facetField = "facet_" + s;
          // facetDim = s;
          // config.setIndexFieldName(s, "facet_" + s);
          config.setHierarchical(s, true);
        }
      }

    }
  }

  private Directory getTaxDirectory(ODatabaseDocumentInternal database) throws IOException {
    final OAbstractPaginatedStorage storageLocalAbstract = (OAbstractPaginatedStorage) database.getStorage().getUnderlying();
    if (storageLocalAbstract instanceof OLocalPaginatedStorage) {
      String pathname = getIndexFacetPath((OLocalPaginatedStorage) storageLocalAbstract);
      return NIOFSDirectory.open(new File(pathname).toPath());
    }

    return new RAMDirectory();

  }

  protected String getIndexFacetPath(OLocalPaginatedStorage storageLocalAbstract) {
    return storageLocalAbstract.getStoragePath() + File.separator + owner.OLUCENE_BASE_DIR + File.separator + owner.name
        + FACET;
  }

  public void delete() {
    ODatabaseDocumentInternal database = owner.getDatabase();
    final OAbstractPaginatedStorage storageLocalAbstract = (OAbstractPaginatedStorage) database.getStorage().getUnderlying();
    if (storageLocalAbstract instanceof OLocalPaginatedStorage) {
      File f = new File(getIndexFacetPath((OLocalPaginatedStorage) storageLocalAbstract));
      OFileUtils.deleteRecursively(f);
      f = new File(owner.getIndexBasePath((OLocalPaginatedStorage) storageLocalAbstract));
      OFileUtils.deleteFolderIfEmpty(f);
    }
  }

  protected Boolean supportsFacets() {
    return taxonomyWriter != null;
  }

  protected boolean isFacetField(String field) {
    if (metadata == null)
      return false;
    if (metadata.field(FACET_FIELDS) == null)
      return false;
    Collection fields = metadata.field(FACET_FIELDS);
    return fields.contains(field);
  }

  protected IndexableField buildFacetField(String f, Object val) {
    String[] path = null;
    if (val instanceof String) {

      path = ((String) val).split("/");
      // path = new String[1];
      // path[0] = (String) val;
    } else if (val instanceof Iterable) {
      Iterable iterable = (Iterable) val;
      List values = new ArrayList();
      for (Object s : iterable) {
        if (s instanceof String) {
          values.add((String) s);
        } else {
          throw new OIndexEngineException("Cannot facet value " + val + " because it is not a string", null);
        }
      }
      path = values.toArray(new String[values.size()]);
    }
    return new FacetField(f, path);
  }

  public Document buildDocument(Document doc) throws IOException {
    return config.build(taxonomyWriter, doc);
  }

  public void commit() {
    try {
      if (taxonomyWriter != null)
        taxonomyWriter.commit();
    } catch (IOException e) {
      OLogManager.instance().error(this, "Error during taxonomy commit", e);
    }
  }

  public void addFacetContext(QueryContext queryContext, Object key) throws IOException {
    queryContext.setFacet(true);
    queryContext.setFacetField(facetField);
    queryContext.setFacetConfig(config);
    // queryContext.setfacetDim(facetDim);
    queryContext.setReader(new DirectoryTaxonomyReader(getTaxDirectory(owner.getDatabase())));

    if (key instanceof OCompositeKey) {
      List keys = ((OCompositeKey) key).getKeys();
      for (Object o : keys) {
        if (o instanceof Map) {
          String drillDown = (String) ((Map) o).get("drillDown");
          queryContext.setDrillDownQuery(drillDown);
        }
      }
    }
  }
}