org.hibernate.search.engine.impl.LuceneOptionsImpl Maven / Gradle / Ivy
/*
* Hibernate Search, full-text search for your domain model
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or .
*/
package org.hibernate.search.engine.impl;
import org.apache.lucene.document.CompressionTools;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.DoubleField;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.TermVector;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.document.FloatField;
import org.apache.lucene.document.IntField;
import org.apache.lucene.document.LongField;
import org.apache.lucene.index.FieldInfo.IndexOptions;
import org.hibernate.search.annotations.Store;
import org.hibernate.search.bridge.LuceneOptions;
import org.hibernate.search.engine.metadata.impl.DocumentFieldMetadata;
import org.hibernate.search.exception.SearchException;
import org.hibernate.search.util.StringHelper;
/**
* A wrapper class for Lucene parameters needed for indexing.
*
* @author Hardy Ferentschik
* @author Sanne Grinovero
* @author Gustavo Fernandes
*/
public class LuceneOptionsImpl implements LuceneOptions {
private static final FieldType TYPE_COMPRESSED = new FieldType();
static {
TYPE_COMPRESSED.setIndexed( false );
TYPE_COMPRESSED.setTokenized( false );
TYPE_COMPRESSED.setOmitNorms( true );
TYPE_COMPRESSED.setIndexOptions( IndexOptions.DOCS_ONLY );
TYPE_COMPRESSED.setStored( true );
TYPE_COMPRESSED.freeze();
}
private final boolean storeCompressed;
private final boolean storeUncompressed;
private boolean documentBoostApplied = false; //needs to be applied only once
private final float fieldLevelBoost;
private final float documentLevelBoost;
private final Index indexMode;
private final TermVector termVector;
private final Store storeType;
private final String indexNullAs;
public LuceneOptionsImpl(DocumentFieldMetadata fieldMetadata, float fieldLevelBoost, float documentLevelBoost) {
this.documentLevelBoost = documentLevelBoost;
this.indexMode = fieldMetadata.getIndex();
this.termVector = fieldMetadata.getTermVector();
this.fieldLevelBoost = fieldLevelBoost;
this.storeType = fieldMetadata.getStore();
this.storeCompressed = this.storeType.equals( Store.COMPRESS );
this.storeUncompressed = this.storeType.equals( Store.YES );
this.indexNullAs = fieldMetadata.indexNullAs();
}
@Override
public void addFieldToDocument(String name, String indexedString, Document document) {
//Do not add fields on empty strings, seems a sensible default in most situations
if ( StringHelper.isNotEmpty( indexedString ) ) {
if ( !( indexMode.equals( Index.NO ) && storeCompressed ) ) {
standardFieldAdd( name, indexedString, document );
}
if ( storeCompressed ) {
compressedFieldAdd( name, indexedString, document );
}
}
}
private void standardFieldAdd(String name, String indexedString, Document document) {
Field field = new Field( name, indexedString, storeUncompressed ? Field.Store.YES : Field.Store.NO, indexMode, termVector );
setBoost( field );
document.add( field );
}
private void compressedFieldAdd(String name, String indexedString, Document document) {
byte[] compressedString = CompressionTools.compressString( indexedString );
// indexed is implicitly set to false when using byte[]
Field field = new Field( name, compressedString, TYPE_COMPRESSED );
document.add( field );
}
@Override
public float getBoost() {
return fieldLevelBoost;
}
@Override
public String indexNullAs() {
return indexNullAs;
}
@Override
public boolean isCompressed() {
return storeCompressed;
}
@Override
public Index getIndex() {
return this.indexMode;
}
@Override
public org.apache.lucene.document.Field.Store getStore() {
if ( storeUncompressed || storeCompressed ) {
return org.apache.lucene.document.Field.Store.YES;
}
else {
return org.apache.lucene.document.Field.Store.NO;
}
}
@Override
public TermVector getTermVector() {
return this.termVector;
}
private void setBoost(Field field) {
/**
* MEMO from the Apache Lucene documentation:
* It is illegal to return a boost other than 1.0f for a field that is not
* indexed ({@link IndexableFieldType#indexed()} is false) or omits normalization values
* ({@link IndexableFieldType#omitNorms()} returns true).
*/
if ( indexMode.isIndexed() && ! indexMode.omitNorms() ) {
if ( documentBoostApplied == false ) {
documentBoostApplied = true;
//FIXME This isn't entirely accurate as in some cases the LuceneOptionsImpl
//is being reused for multiple fields: this needs to be significantly different,
//potentially dropping the LuceneOptionsImpl usage.
field.setBoost( fieldLevelBoost * documentLevelBoost );
}
else {
field.setBoost( fieldLevelBoost );
}
}
}
private void checkNotCompressed(final String fieldName) {
//TODO this sanity check should be done at bootstrap, not runtime
if ( storeType == Store.COMPRESS ) {
throw new SearchException( "Error indexing field " + fieldName + ", @NumericField cannot be compressed" );
}
}
public void addDoubleFieldToDocument(String fieldName, double doubleValue, Document document) {
checkNotCompressed( fieldName );
DoubleField field = new DoubleField( fieldName, doubleValue, storeType != Store.NO ? Field.Store.YES : Field.Store.NO );
setBoost( field );
document.add( field );
}
public void addFloatFieldToDocument(String fieldName, float floatValue, Document document) {
checkNotCompressed( fieldName );
FloatField field = new FloatField( fieldName, floatValue, storeType != Store.NO ? Field.Store.YES : Field.Store.NO );
setBoost( field );
document.add( field );
}
public void addIntFieldToDocument(String fieldName, int intValue, Document document) {
checkNotCompressed( fieldName );
IntField field = new IntField( fieldName, intValue, storeType != Store.NO ? Field.Store.YES : Field.Store.NO );
setBoost( field );
document.add( field );
}
public void addLongFieldToDocument(String fieldName, long longValue, Document document) {
checkNotCompressed( fieldName );
LongField field = new LongField( fieldName, longValue, storeType != Store.NO ? Field.Store.YES : Field.Store.NO );
setBoost( field );
document.add( field );
}
@Override
public void addNumericFieldToDocument(String fieldName, Object indexedValue, Document document) {
if ( indexedValue == null ) {
throw new IllegalArgumentException( "the indexedValue parameter shall not be null" );
}
if ( indexedValue instanceof Double ) {
addDoubleFieldToDocument( fieldName, ( (Double) indexedValue ).doubleValue(), document );
}
else if ( indexedValue instanceof Float ) {
addFloatFieldToDocument( fieldName, ( (Float) indexedValue ).floatValue(), document );
}
else if ( indexedValue instanceof Integer ) {
addIntFieldToDocument( fieldName, ( (Integer) indexedValue ).intValue(), document );
}
else if ( indexedValue instanceof Long ) {
addLongFieldToDocument( fieldName, ( (Long) indexedValue ).longValue(), document );
}
else {
throw new IllegalArgumentException( "unsupported type of Number" );
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy