Search code examples
javahibernatehibernate-search

Using Hibernate Search 6 - How to prevent automatic indexing for a specific entity?


We would like to handle the indexing ourselves for one of our Hibernate Search entities.

Is it possible to disable auto indexing within Hibernate Search 6 for a specific entity? Similar to the older Hibernate Search global setting: hibernate.search.indexing_strategy = manual

I've searched through the documentation but haven't seen this mentioned.


Solution

  • hibernate.search.indexing_strategy = manual was for all entity types, not for a specific one.

    The feature you're looking for has already been filed as HSEARCH-168, and is currently planned for Hibernate Search 6.2.

    In the meantime, I think the best you can do would be to rely on a hack. It won't be as efficient as what we envision for HSEARCH-168, but it's a start:

    • Implement a RoutingBridge which, based on a switch, will either disable indexing completely (both adding and removing the entity from the index) or behave normally as if there was no routing bridge:
      public class ManualIndexingRoutingBinder implements RoutingBinder {
      
          private static volatile boolean indexingEnabled = false;
      
          public static synchronized void withIndexingEnabled(Runnable runnable) {
              indexingEnabled = true;
              try {
                  runnable.run();
              }
              finally {
                  indexingEnabled = false;
              }
          }
      
          @Override
          public void bind(RoutingBindingContext context) { 
              context.dependencies() 
                      .useRootOnly();
      
              context.bridge( 
                      Book.class, 
                      new Bridge() 
              );
          }
      
          public static class Bridge implements RoutingBridge<Book> { 
              @Override
              public void route(DocumentRoutes routes, Object entityIdentifier, Book indexedEntity, 
                      RoutingBridgeRouteContext context) {
                  if ( indexingEnabled ) { 
                      routes.addRoute();
                  }
                  else {
                      routes.notIndexed(); 
                  }
              }
      
              @Override
              public void previousRoutes(DocumentRoutes routes, Object entityIdentifier, Book indexedEntity, 
                      RoutingBridgeRouteContext context) {
                  if ( indexingEnabled ) {
                      // So that Hibernate Search will correctly delete entities if necessary.
                      // Only useful if you use SearchIndexingPlan for manual indexing,
                      // as the MassIndexer never deletes documents.
                      routes.addRoute();
                  }
                  else {
                      routes.notIndexed(); 
                  }
              }
          }
      }
      
    • Apply that routing bridge to the entity types you want to control:
      @Entity
      @Indexed(routingBinder = @RoutingBinderRef(type = ManualIndexingRoutingBinder.class))
      public class Book {
          // ...
      }
      
    • The routing bridge will effectively disable automatic indexing.
    • To index manually, do this:
      ManualIndexingRoutingBinder.withIndexingEnabled(() -> {
          Search.mapping(entityManagerFactory).scope(Book.class)
                  .massIndexer()
                  .startAndWait();
      });
      

    I didn't test this exactly, so please report back, but in principle this should work.