Conditional indexing

There are specialized ways to go about indexing fields, such as using a class bridge or the programmatic mapping API. Generally speaking, though, a property is indexed when it is annotated with @Field. Therefore, one obvious way to avoid indexing a field is to simply not apply the annotation.

However, what if we want an entity class to be searchable in general, but we need to exclude certain instances of that class, based on the state of their data at runtime?

The @Indexed annotation has an experimental second element, interceptor , that gives us the ability to index conditionally. When this element is set, the normal indexing process will be intercepted by custom code, which can prevent an entity from being indexed based on its current state.

Let's give our VAPORware Marketplace the ability to make apps inactive. Inactive apps will still exist in the database, but should not be shown to customers or indexed for searching. To start, we will add a new property to the App entity class:

...
@Column
private boolean active;
...
public App(String name, String image, String description) {
   this.name = name;
   this.image = image;
   this.description = description;
   this.active = true;
}
...
public booleanisActive() {
   return active;
}
public void setActive(boolean active) {
   this.active = active;
}
...

This new active variable has the standard getter and setter methods, and is being defaulted to true in our normal constructor. We want individual apps to be excluded from the Lucene index when this variable is false, so we add an interceptor element to the @Indexed annotation:

...
import com.packtpub.hibernatesearch.util.IndexWhenActiveInterceptor;
...
@Entity
@Indexed(interceptor=IndexWhenActiveInterceptor.class)
public class App {
...

This element must be tied to a class that implements the EntityIndexingInterceptor interface. Since we just specified a class named IndexWhenActiveInterceptor, we need to now create this class.

package com.packtpub.hibernatesearch.util;

import org.hibernate.search.indexes.interceptor.EntityIndexingInterceptor;
import org.hibernate.search.indexes.interceptor.IndexingOverride;
import com.packtpub.hibernatesearch.domain.App;

public class IndexWhenActiveInterceptor
      implementsEntityIndexingInterceptor<App> {

   /** Only index newly-created App's when they are active */
   public IndexingOverrideonAdd(App entity) {
      if(entity.isActive()) {
         return IndexingOverride.APPLY_DEFAULT;
      }
      return IndexingOverride.SKIP;
   }
   public IndexingOverrideonDelete(App entity) {
      return IndexingOverride.APPLY_DEFAULT;
   }

   /** Index active App's, and remove inactive ones */
   public IndexingOverrideonUpdate(App entity) {
      if(entity.isActive()) {
         return IndexingOverride.UPDATE;
            } else {
         return IndexingOverride.REMOVE;
      }
   }

   public IndexingOverrideonCollectionUpdate(App entity) {
      retur nonUpdate(entity);
   }

}

The EntityIndexingInterceptor interface declares four methods, which Hibernate Search will call at various points during an entity object's life cycle:

  • onAdd(): This is called when the entity instance is first created.
  • onDelete(): This is called when the entity instance is removed from the database.
  • onUpdate(): This is called when an existing instance is updated.
  • onCollectionUpdate(): This version is used when an entity is modified as part of a bulk update with other entities. Typically, implementations of this method simply invoke onUpdate().

Each of these methods should return one of the four possible IndexingOverride enum values. The possible return values tell Hibernate Search what to do:

  • IndexingOverride.SKIP: This tells Hibernate Search to not modify the Lucene index for this entity instance at this time.
  • IndexingOverride.REMOVE: Hibernate Search will remove the entity if it already exists in an index, or else will do nothing if the entity is not indexed.
  • IndexingOverride.UPDATE: The entity will be updated in the index, or added if it is not already indexed.
  • IndexingOverride.APPLY_DEFAULT: This is equivalent to the custom interceptor not being used in the first place. Hibernate Search will index the entity if this is an onAdd() operation, remove it from the index if this is an onDelete(), or update the index if this is onUpdate() or onCollectionUpdate().

Although the four methods logically imply certain return values, it is actually possible to mix them in any combination if you are dealing with unusual conditions.

In our example application, our interceptor examines the entity in onAdd() and onDelete(). When a new App is created, indexing is skipped if its active variable is false. When an App is updated, it will be removed from the index if has become inactive.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset