Hibernate Search Documentation

repository·main·Indexed 19 days ago

https://github.com/hibernate/hibernate-search

Full-text search integration for Hibernate ORM that synchronizes database entities with Lucene, Elasticsearch, or OpenSearch indexes. Features include automatic indexing via annotations (@Indexed, @FullTextField), a type-safe Search DSL for complex queries, mass indexing, and support for spatial coordinates. The architecture consists of a user-facing Mapper layer, an Engine, and interchangeable Backends.

Tokens
103.8K
Snippets
201
Records
446
Agent score
65%

What's inside Hibernate Search

  1. Overview of Hibernate Search

    main

    Hibernate Search is a full-text search engine integration for Hibernate ORM. It automatically extracts data from Hibernate ORM entities and synchronizes it with search indexes.

    Key capabilities include:

    • Automatic Indexing: Supports local Apache Lucene indexes or remote Elasticsearch/OpenSearch indexes.
    • Declarative Mapping: Map entity properties to index fields using annotations or a programmatic API.
    • Mass Indexing: On-demand indexing of all existing database entities to initialize indexes.
    • Automatic Synchronization: Listener-triggered indexing ensures that entities modified via a Hibernate ORM session are automatically updated in the index.
    • Search DSL: A type-safe Domain Specific Language to build complex full-text queries and retrieve results as Hibernate ORM entities.
  2. Tuning when to trigger reindexing

    main

    Hibernate Search automatically detects changes to mapped properties (via @GenericField, @IndexedEmbedded, or custom bridges) and triggers reindexing. However, certain mapping scenarios require explicit configuration to ensure the index stays synchronized or to prevent performance issues.

    Key Scenarios Requiring Configuration:

    • Derived Properties: Properties computed in a getter that depend on other persistent state. Hibernate Search cannot automatically guess these dependencies.
    • Cross-Entity Associations: When an entity is @IndexedEmbedded, changes to the associated entity must trigger reindexing of the containing entity. This typically requires a bidirectional association.
    • Massive or High-Frequency Updates: When associations are too large to traverse or properties change too frequently for real-time reindexing.
  3. What is a Routing Bridge and how does it work?

    main

    A Routing Bridge is a pluggable component that determines at runtime whether an entity should be indexed and to which index shard the corresponding document should be routed.

    It is applied to an entity type annotated with @Indexed using the routingBinder attribute: @Indexed(routingBinder = ...).

    Implementing a routing bridge requires two components:

    1. RoutingBinder: A custom implementation used to bind the bridge to an entity type at bootstrap. It declares which entity properties the bridge depends on and instantiates the bridge.
    2. RoutingBridge: A custom implementation that executes at runtime. It extracts data from the entity instance, transforms it, and defines the current route or marks the entity as notIndexed().

    Important: Handling Route Changes If an entity's routing information can change during its lifetime (e.g., a property used for routing is updated), you must implement the previousRoutes(...) method in your RoutingBridge. This allows Hibernate Search to find and delete the old document in the previous shard/route when the entity moves to a new one.

  4. What is a Value Bridge and when to use it

    main

    A ValueBridge is a pluggable component used to map a property from your entity model to an index field in the document model. It is ideal for converting a property of one type into a different type for indexing (e.g., converting a custom ISBN object into a String).

    Key Characteristics

    • One-to-One Mapping: A single value bridge can only map one property to exactly one index field.
    • Atomic Data Only: Value bridges should be applied to "atomic" data (like LocalDate or String). Do not apply them to mutable entities; Hibernate Search cannot detect changes to the entity's internal properties, which means reindexing will not be triggered when those properties change.
    • Container Support: They can be applied transparently to containers. For example, a ValueBridge<ISBN, String> applied to a List<ISBN> will be applied to each element in the list.
    • Integration: They work seamlessly with @*Field annotations (like @FullTextField, @GenericField, etc.), allowing you to use standard features like sortable, projectable, or analyzer on the resulting index field.
  5. Overview of Hibernate Search Query DSL

    main

    Hibernate Search provides high-level APIs (a Query DSL) to search indexed data without using native search engine APIs.

    A primary capability of this DSL is the ability to use the search index to drive queries that return Hibernate ORM entities loaded directly from the database. This allows you to perform complex full-text searches while maintaining the benefits of Hibernate's entity management and lifecycle.

  6. What is the Hibernate Search static metamodel?

    main

    The Hibernate Search static metamodel is a set of generated classes that represents the structure of each entity's index. It allows you to use type-safe references to index fields when constructing search queries using the Search DSL, rather than relying on string-based field names. This approach reduces errors caused by typos and provides better IDE support (autocompletion) for your search queries.

    While the concept is similar to the JPA static metamodel used in Hibernate ORM, the Search metamodel specifically describes the structure of your indexes rather than your database entities.

  7. What is Hibernate Search and how does it work?

    main

    Hibernate Search is a full-text search engine integration that bridges the gap between object domain models and search technologies like Apache Lucene, Elasticsearch, or OpenSearch.

    It solves common mismatches between domain models and search indexes by:

    1. Indexing via Annotations: You index your domain model using a few simple annotations.
    2. Automatic Synchronization: It handles the synchronization between your database and the search index.
    3. Object-Oriented Queries: It returns regular managed objects (from Hibernate ORM) directly from free-text queries, rather than just raw search hits.
  8. What is a Property Bridge and when to use it

    main

    A Property Bridge is a pluggable component used to map a single property to one or more index fields. It is applied to a property using the @PropertyBinding annotation or a custom annotation.

    Key Characteristics

    • Complexity: More complex to implement than a ValueBridge.
    • Capabilities:
      • Can map one property to multiple index fields.
      • Can work correctly with mutable types if implemented correctly.
    • Limitations: Unlike ValueBridge, it does not automatically provide features like container extractors. You must implement container value extraction explicitly.

    Implementation Requirements

    Implementing a property bridge requires two distinct components:

    1. PropertyBinder: Used at bootstrap to bind the bridge to a property. It declares dependencies (to ensure correct reindexing), declares the index fields and their types, and instantiates the bridge.
    2. PropertyBridge: Used at runtime to perform the actual conversion. It extracts data from the property, transforms it, and pushes it to the index fields.
  9. What is the static metamodel in Hibernate Search?

    main

    The static metamodel is a set of generated classes that describe your index structure at compile time. Each indexed entity is represented by a root metamodel class, which may contain inner classes for indexed-embedded properties.

    These classes provide:

    1. Type-safe field references: Instead of using string-based field names (e.g., .field("title")), you use generated field references (e.g., Book__.title). This enables compile-time checks for your queries.
    2. Search Scope simplification: Using the metamodel's INDEX constant helps create a search scope that automatically limits acceptable field references to those valid for that specific index.
    3. Search Capability Enforcement: Field reference types implement specific "trait" interfaces that define what operations (projections, aggregations, predicates, sorts) are valid for that specific field.
  10. What is the Standalone POJO Mapper?

    main

    The Standalone POJO Mapper allows you to map arbitrary POJOs (Plain Old Java Objects) to search indexes without requiring Hibernate ORM or a relational database.

    It is useful for indexing entities from arbitrary datastores or using Lucene/Elasticsearch as a primary datastore. However, because it does not assume an underlying ORM, it requires more explicit configuration than the Hibernate ORM integration:

    • No automatic change detection: All indexing must be triggered explicitly via an indexing plan.
    • Manual entity loading: You must implement strategies to load entities when performing search queries or mass indexing.
    • No node coordination: It does not currently provide coordination between different nodes in a cluster.
    • No transaction support: Indexing is executed on session closing rather than on transaction commit.
  11. How searching works in Hibernate Search

    main

    Searching in Hibernate Search is designed to be index-centric, even when using user-friendly APIs.

    • User API: Mappers provide entry points that allow users to define search scope naturally (e.g., using Java classes instead of index names).
    • Generic APIs: Under the hood, mappers expose generic APIs like SearchQueryResultDefinitionContext or SearchPredicateContainerContext, which are implemented by the engine.
    • Backend SPIs: The engine relies on lower-level SPIs implemented by backends, such as SearchPredicateFactory or FieldSortBuilder.
    • Entity Loading: To transform document references back into the original entities, backends use a "loading context" injected via SearchQueryBuilderFactory.selectEntity.