Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HSEARCH-5010 Lucene 10 backend #4401

  •  
  •  
  •  
118 changes: 118 additions & 0 deletions backend/lucene10/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-parent-public</artifactId>
<version>8.0.0-SNAPSHOT</version>
<relativePath>../../build/parents/public</relativePath>
</parent>
<artifactId>hibernate-search-backend-lucene10</artifactId>

<name>Hibernate Search Backend - Lucene 10</name>
<description>Hibernate Search Backend relying on embedded instances of Lucene (v10)</description>

<properties>
<!-- This is a publicly distributed module that should be published: -->
<deploy.skip>false</deploy.skip>
<java.module.name>org.hibernate.search.backend.lucene</java.module.name>

<version.org.apache.lucene>10.0.0</version.org.apache.lucene>
<java-version.main.release>21</java-version.main.release>
</properties>

<dependencyManagement>
<dependencies>
<!-- Lucene backend -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>${version.org.apache.lucene}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analysis-common</artifactId>
<version>${version.org.apache.lucene}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
<version>${version.org.apache.lucene}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-join</artifactId>
<version>${version.org.apache.lucene}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-facet</artifactId>
<version>${version.org.apache.lucene}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-highlighter</artifactId>
<version>${version.org.apache.lucene}</version>
</dependency>
<dependency>
<groupId>com.carrotsearch</groupId>
<artifactId>hppc</artifactId>
<version>${version.com.carrotsearch.hppc}</version>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-engine</artifactId>
</dependency>

<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analysis-common</artifactId>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-join</artifactId>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-facet</artifactId>
</dependency>
<dependency>
<groupId>com.carrotsearch</groupId>
<artifactId>hppc</artifactId>
</dependency>

<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-highlighter</artifactId>
</dependency>

<!-- Test -->
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-util-internal-test-common</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.search.backend.lucene;

import java.util.Optional;

import org.hibernate.search.engine.backend.Backend;
import org.hibernate.search.engine.backend.metamodel.IndexValueFieldTypeDescriptor;

import org.apache.lucene.analysis.Analyzer;

public interface LuceneBackend extends Backend {

/**
* @param name An analyzer name, e.g. a name returned by {@link IndexValueFieldTypeDescriptor#analyzerName()}
* or {@link IndexValueFieldTypeDescriptor#searchAnalyzerName()}.
* @return The corresponding analyzer, or {@link Optional#empty()} if it doesn't exist.
*/
Optional<? extends Analyzer> analyzer(String name);

/**
* @param name A normalizer name, e.g. a name returned by {@link IndexValueFieldTypeDescriptor#normalizerName()}.
* @return The corresponding normalizer, or {@link Optional#empty()} if it doesn't exist.
*/
Optional<? extends Analyzer> normalizer(String name);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.search.backend.lucene;

import java.util.Optional;

import org.hibernate.search.backend.lucene.logging.impl.LuceneMiscLog;
import org.hibernate.search.backend.lucene.schema.management.LuceneIndexSchemaExport;
import org.hibernate.search.backend.lucene.scope.LuceneIndexScope;
import org.hibernate.search.backend.lucene.search.aggregation.dsl.LuceneSearchAggregationFactory;
import org.hibernate.search.backend.lucene.search.predicate.dsl.LuceneSearchPredicateFactory;
import org.hibernate.search.backend.lucene.search.projection.dsl.LuceneSearchProjectionFactory;
import org.hibernate.search.backend.lucene.search.query.LuceneSearchQuery;
import org.hibernate.search.backend.lucene.search.query.dsl.LuceneSearchQuerySelectStep;
import org.hibernate.search.backend.lucene.search.query.dsl.impl.LuceneSearchQuerySelectStepImpl;
import org.hibernate.search.backend.lucene.search.query.impl.LuceneSearchQueryIndexScope;
import org.hibernate.search.backend.lucene.search.sort.dsl.LuceneSearchSortFactory;
import org.hibernate.search.backend.lucene.types.dsl.LuceneIndexFieldTypeFactory;
import org.hibernate.search.engine.backend.scope.IndexScopeExtension;
import org.hibernate.search.engine.backend.scope.spi.IndexScope;
import org.hibernate.search.engine.backend.session.spi.BackendSessionContext;
import org.hibernate.search.engine.backend.types.dsl.IndexFieldTypeFactory;
import org.hibernate.search.engine.backend.types.dsl.IndexFieldTypeFactoryExtension;
import org.hibernate.search.engine.common.schema.management.SchemaExport;
import org.hibernate.search.engine.common.schema.management.SchemaExportExtension;
import org.hibernate.search.engine.search.aggregation.dsl.SearchAggregationFactory;
import org.hibernate.search.engine.search.aggregation.dsl.SearchAggregationFactoryExtension;
import org.hibernate.search.engine.search.loading.spi.SearchLoadingContext;
import org.hibernate.search.engine.search.loading.spi.SearchLoadingContextBuilder;
import org.hibernate.search.engine.search.predicate.dsl.SearchPredicateFactory;
import org.hibernate.search.engine.search.predicate.dsl.SearchPredicateFactoryExtension;
import org.hibernate.search.engine.search.projection.dsl.SearchProjectionFactory;
import org.hibernate.search.engine.search.projection.dsl.SearchProjectionFactoryExtension;
import org.hibernate.search.engine.search.query.SearchQuery;
import org.hibernate.search.engine.search.query.SearchQueryExtension;
import org.hibernate.search.engine.search.query.dsl.SearchQueryDslExtension;
import org.hibernate.search.engine.search.query.dsl.SearchQuerySelectStep;
import org.hibernate.search.engine.search.query.spi.SearchQueryIndexScope;
import org.hibernate.search.engine.search.sort.dsl.SearchSortFactory;
import org.hibernate.search.engine.search.sort.dsl.SearchSortFactoryExtension;

/**
* An extension for the Lucene backend, giving access to Lucene-specific features.
* <p>
* <strong>WARNING:</strong> while this type is API, because instances should be manipulated by users,
* all of its methods are considered SPIs and therefore should never be called directly by users.
* In short, users are only expected to get instances of this type from an API and pass it to another API.
*
* @param <H> The type of query hits.
* Users should not have to care about this, as the parameter will automatically take the appropriate value when calling
* {@code .extension( LuceneExtension.get() )}.
* @param <R> The entity reference type for projections.
* Users should not have to care about this, as the parameter will automatically take the appropriate value when calling
* {@code .extension( LuceneExtension.get() )}.
* @param <E> entity type for projections.
* Users should not have to care about this, as the parameter will automatically take the appropriate value when calling
* {@code .extension( LuceneExtension.get() )}.
* @param <LOS> The type of the initial step of the loading options definition DSL.
* Users should not have to care about this, as the parameter will automatically take the appropriate value when calling
* {@code .extension( LuceneExtension.get() )}.
*
* @see #get()
*/
public final class LuceneExtension<H, R, E, LOS>
implements SearchQueryDslExtension<LuceneSearchQuerySelectStep<R, E, LOS>, R, E, LOS>,
SearchQueryExtension<LuceneSearchQuery<H>, H>,
SearchPredicateFactoryExtension<LuceneSearchPredicateFactory>,
SearchSortFactoryExtension<LuceneSearchSortFactory>,
SearchProjectionFactoryExtension<LuceneSearchProjectionFactory<R, E>, R, E>,
SearchAggregationFactoryExtension<LuceneSearchAggregationFactory>,
IndexFieldTypeFactoryExtension<LuceneIndexFieldTypeFactory>,
IndexScopeExtension<LuceneIndexScope>,
SchemaExportExtension<LuceneIndexSchemaExport> {

private static final LuceneExtension<Object, Object, Object, Object> INSTANCE = new LuceneExtension<>();

/**
* Get the extension with generic parameters automatically set as appropriate for the context in which it's used.
*
* @param <H> The type of query hits.
* Users should not have to care about this, as the parameter will automatically take the appropriate value when calling
* {@code .extension( LuceneExtension.get() }.
* @param <R> The entity reference type for projections.
* Users should not have to care about this, as the parameter will automatically take the appropriate value when calling
* {@code .extension( LuceneExtension.get() }.
* @param <E> entity type for projections.
* Users should not have to care about this, as the parameter will automatically take the appropriate value when calling
* {@code .extension( LuceneExtension.get() }.
* @param <LOS> The type of the initial step of the loading options definition DSL.
* Users should not have to care about this, as the parameter will automatically take the appropriate value when calling
* {@code .extension( LuceneExtension.get() }.
* @return The extension.
*/
@SuppressWarnings("unchecked") // The instance works for any H, R and E
public static <H, R, E, LOS> LuceneExtension<H, R, E, LOS> get() {
return (LuceneExtension<H, R, E, LOS>) INSTANCE;
}

private LuceneExtension() {
// Private constructor, use get() instead.
}

/**
* {@inheritDoc}
*/
@Override
public Optional<LuceneSearchQuerySelectStep<R, E, LOS>> extendOptional(
SearchQuerySelectStep<?, R, E, LOS, ?, ?> original,
SearchQueryIndexScope<?> scope,
BackendSessionContext sessionContext,
SearchLoadingContextBuilder<E, LOS> loadingContextBuilder) {
if ( scope instanceof LuceneSearchQueryIndexScope ) {
return Optional.of( new LuceneSearchQuerySelectStepImpl<>(
(LuceneSearchQueryIndexScope<?>) scope, sessionContext, loadingContextBuilder
) );
}
else {
return Optional.empty();
}
}

/**
* {@inheritDoc}
*/
@Override
public Optional<LuceneSearchQuery<H>> extendOptional(SearchQuery<H> original,
SearchLoadingContext<?> loadingContext) {
if ( original instanceof LuceneSearchQuery ) {
return Optional.of( (LuceneSearchQuery<H>) original );
}
else {
return Optional.empty();
}
}

/**
* {@inheritDoc}
*/
@Override
public Optional<LuceneSearchPredicateFactory> extendOptional(SearchPredicateFactory original) {
if ( original instanceof LuceneSearchPredicateFactory ) {
return Optional.of( (LuceneSearchPredicateFactory) original );
}
else {
return Optional.empty();
}
}

/**
* {@inheritDoc}
*/
@Override
public Optional<LuceneSearchSortFactory> extendOptional(
SearchSortFactory original) {
if ( original instanceof LuceneSearchSortFactory ) {
return Optional.of( (LuceneSearchSortFactory) original );
}
else {
return Optional.empty();
}
}

/**
* {@inheritDoc}
*/
@Override
public Optional<LuceneSearchProjectionFactory<R, E>> extendOptional(SearchProjectionFactory<R, E> original) {
if ( original instanceof LuceneSearchProjectionFactory ) {
return Optional.of( (LuceneSearchProjectionFactory<R, E>) original );
}
else {
return Optional.empty();
}
}

/**
* {@inheritDoc}
*/
@Override
public Optional<LuceneSearchAggregationFactory> extendOptional(SearchAggregationFactory original) {
if ( original instanceof LuceneSearchAggregationFactory ) {
return Optional.of( (LuceneSearchAggregationFactory) original );
}
else {
return Optional.empty();
}
}

/**
* {@inheritDoc}
*/
@Override
public LuceneIndexFieldTypeFactory extendOrFail(IndexFieldTypeFactory original) {
if ( original instanceof LuceneIndexFieldTypeFactory ) {
return (LuceneIndexFieldTypeFactory) original;
}
else {
throw LuceneMiscLog.INSTANCE.luceneExtensionOnUnknownType( original );
}
}

/**
* {@inheritDoc}
*/
@Override
public LuceneIndexScope extendOrFail(IndexScope original) {
if ( original instanceof LuceneIndexScope ) {
return (LuceneIndexScope) original;
}
else {
throw LuceneMiscLog.INSTANCE.luceneExtensionOnUnknownType( original );
}
}

/**
* {@inheritDoc}
*/
@Override
public LuceneIndexSchemaExport extendOrFail(SchemaExport original) {
if ( original instanceof LuceneIndexSchemaExport ) {
return (LuceneIndexSchemaExport) original;
}
else {
throw LuceneMiscLog.INSTANCE.luceneExtensionOnUnknownType( original );
}
}
}
Loading
Loading