Skip to content

Commit

Permalink
HSEARCH-3319 WIP: DRAFT: IDEA: TEST: Type-safe field references
Browse files Browse the repository at this point in the history
  • Loading branch information
marko-bekhta committed Apr 23, 2024
1 parent f3bb0ec commit e5c26f9
Show file tree
Hide file tree
Showing 35 changed files with 1,371 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import org.hibernate.search.documentation.testsupport.DocumentationSetupHelper;
import org.hibernate.search.engine.backend.types.Projectable;
import org.hibernate.search.engine.search.common.ValueConvert;
import org.hibernate.search.engine.search.reference.TypedFieldReference;
import org.hibernate.search.engine.search.reference.ValueFieldReference;
import org.hibernate.search.mapper.orm.Search;
import org.hibernate.search.mapper.orm.session.SearchSession;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.Indexed;
Expand All @@ -34,7 +36,8 @@

class ProjectionConverterIT {
@RegisterExtension
public DocumentationSetupHelper setupHelper = DocumentationSetupHelper.withSingleBackend( BackendConfigurations.simple() );
public DocumentationSetupHelper setupHelper = DocumentationSetupHelper.withSingleBackend(
BackendConfigurations.simple() );

private EntityManagerFactory entityManagerFactory;

Expand Down Expand Up @@ -80,6 +83,73 @@ void projectionConverterDisabled() {
} );
}

@Test
void projectionConverterDisabledFR() {
with( entityManagerFactory ).runInTransaction( entityManager -> {
SearchSession searchSession = Search.session( entityManager );
// "status", String.class, ValueConvert.NO


ValueFieldReference<OrderStatus, String> reference = new ValueFieldReference<>() {
private final String absolutePath = "status";

@Override
public String absolutePath() {
return absolutePath;
}

@Override
public Class<OrderStatus> type() {
return OrderStatus.class;
}

@Override
public TypedFieldReference<String> noConverter() {
return new TypedFieldReference<>() {
@Override
public String absolutePath() {
return absolutePath;
}

@Override
public Class<String> type() {
return String.class;
}

@Override
public ValueConvert valueConvert() {
return ValueConvert.NO;
}
};
}

@Override
public TypedFieldReference<String> asString() {
throw new UnsupportedOperationException( "PARSE is not supported for projections" );
}
};

List<String> result = searchSession.search( Order.class )
.select( f -> f.field( reference.noConverter() ) )
.where( f -> f.matchAll() )
.fetchHits( 20 );

assertThat( result )
.containsExactlyInAnyOrder(
Stream.of( OrderStatus.values() ).map( Enum::name ).toArray( String[]::new )
);

List<OrderStatus> result2 = searchSession.search( Order.class )
.select( f -> f.field( reference ) )
.where( f -> f.matchAll() )
.fetchHits( 20 );

assertThat( result2 )
.containsExactlyInAnyOrder( OrderStatus.values() );
} );

}

private void initData() {
with( entityManagerFactory ).runInTransaction( entityManager -> {
Order order1 = new Order( 1 );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import org.hibernate.search.engine.search.common.RewriteMethod;
import org.hibernate.search.engine.search.predicate.dsl.RegexpQueryFlag;
import org.hibernate.search.engine.search.predicate.dsl.SimpleQueryFlag;
import org.hibernate.search.engine.search.reference.TypedFieldReference;
import org.hibernate.search.engine.search.reference.ValueFieldReference;
import org.hibernate.search.engine.spatial.DistanceUnit;
import org.hibernate.search.engine.spatial.GeoBoundingBox;
import org.hibernate.search.engine.spatial.GeoPoint;
Expand Down Expand Up @@ -467,6 +469,39 @@ void match() {
} );
}

@Test
void matchFieldReference() {
withinSearchSession( searchSession -> {
List<Book> hits = searchSession.search( Book.class )
.where( f -> f.match().field( new ValueFieldReference<String, String>() {
@Override
public String absolutePath() {
return "title";
}

@Override
public Class<String> type() {
return String.class;
}

@Override
public TypedFieldReference<String> noConverter() {
return null;
}

@Override
public TypedFieldReference<String> asString() {
return null;
}
} )
.matching( "robot" ) )
.fetchHits( 20 );
assertThat( hits )
.extracting( Book::getId )
.containsExactlyInAnyOrder( BOOK1_ID, BOOK3_ID );
} );
}

@Test
void match_analysis() {
withinSearchSession( searchSession -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
*/
package org.hibernate.search.engine.search.predicate.dsl;

import org.hibernate.search.engine.search.reference.TypedFieldReference;
import org.hibernate.search.util.common.annotation.Incubating;

/**
* The step in a query string predicate definition, where the query string to match can be set
* (see the superinterface {@link CommonQueryStringPredicateMatchingStep}),
Expand Down Expand Up @@ -54,4 +57,46 @@ default S field(String fieldPath) {
*/
S fields(String... fieldPaths);

/**
* Target the given field in the query string predicate,
* as an alternative to the already-targeted fields.
* <p>
* Only text fields are supported.
* <p>
* See {@link CommonQueryStringPredicateFieldStep#field(String)} for more information on targeted fields.
*
* @param field The field reference representing a <a href="SearchPredicateFactory.html#field-paths">path</a> to the index field
* to apply the predicate on.
* @return The next step.
*
* @see CommonQueryStringPredicateFieldStep#field(String)
*/
@Incubating
default S field(TypedFieldReference<?> field) {
return fields( field );
}

/**
* Target the given fields in the query string predicate,
* as an alternative to the already-targeted fields.
* <p>
* Only text fields are supported.
* <p>
* See {@link CommonQueryStringPredicateFieldStep#fields(String...)} for more information on targeted fields.
*
* @param fields The field reference representing <a href="SearchPredicateFactory.html#field-paths">paths</a> to the index fields
* to apply the predicate on.
* @return The next step.
*
* @see CommonQueryStringPredicateFieldStep#fields(String...)
*/
@Incubating
default S fields(TypedFieldReference<?>... fields) {
String[] paths = new String[fields.length];
for ( int i = 0; i < fields.length; i++ ) {
paths[i] = fields[i].absolutePath();
}
return fields( paths );
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
*/
package org.hibernate.search.engine.search.predicate.dsl;

import org.hibernate.search.engine.search.reference.TypedFieldReference;
import org.hibernate.search.util.common.annotation.Incubating;

/**
* The initial step in a query string predicate definition, where the target field can be set.
*
Expand Down Expand Up @@ -51,4 +54,50 @@ default N field(String fieldPath) {
*/
N fields(String... fieldPaths);


/**
* Target the given field in the query string predicate.
* <p>
* Only text fields are supported.
* <p>
* Multiple fields may be targeted by the same predicate:
* the predicate will match if <em>any</em> targeted field matches.
* <p>
* When targeting multiple fields, those fields must have compatible types.
* Please refer to the reference documentation for more information.
*
* @param field The field reference representing a <a href="SearchPredicateFactory.html#field-paths">path</a> to the index field
* to apply the predicate on.
* @return The next step.
*/
@Incubating
default N field(TypedFieldReference<?> field) {
return fields( field );
}

/**
* Target the given fields in the query string predicate.
* <p>
* Only text fields are supported.
* <p>
* Equivalent to {@link #field(String)} followed by multiple calls to
* {@link #field(String)},
* the only difference being that calls to {@link CommonQueryStringPredicateFieldMoreStep#boost(float)}
* and other field-specific settings on the returned step will only need to be done once
* and will apply to all the fields passed to this method.
*
* @param fields The field reference representing <a href="SearchPredicateFactory.html#field-paths">paths</a> to the index fields
* to apply the predicate on.
* @return The next step.
*
* @see #field(String)
*/
@Incubating
default N fields(TypedFieldReference<?>... fields) {
String[] paths = new String[fields.length];
for ( int i = 0; i < fields.length; i++ ) {
paths[i] = fields[i].absolutePath();
}
return fields( paths );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
package org.hibernate.search.engine.search.predicate.dsl;


import org.hibernate.search.engine.search.reference.TypedFieldReference;

/**
* The initial step in an "exists" predicate definition, where the target field can be set.
*
Expand All @@ -23,4 +25,15 @@ public interface ExistsPredicateFieldStep<N extends ExistsPredicateOptionsStep<?
*/
N field(String fieldPath);

/**
* Target the given field in the "exists" predicate.
*
* @param field The field reference representing a <a href="SearchPredicateFactory.html#field-paths">path</a> to the index field
* to apply the predicate on.
* @return The next step.
*/
default N field(TypedFieldReference<?> field) {
return field( field.absolutePath() );
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
*/
package org.hibernate.search.engine.search.predicate.dsl;

import org.hibernate.search.engine.search.reference.TypedFieldReference;

/**
* The initial step in a "knn" predicate definition, where the target field can be set.
*/
Expand All @@ -18,4 +20,6 @@ public interface KnnPredicateFieldStep {
* @return The next step in the knn predicate DSL.
*/
KnnPredicateVectorStep field(String fieldPath);

<T> KnnPredicateVectorGenericStep<T> field(TypedFieldReference<T> field);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.search.engine.search.predicate.dsl;

/**
* The step in a "knn" predicate definition where the vector to match is defined.
*/
public interface KnnPredicateVectorGenericStep<T> {
/**
* @param vector The vector from which to compute the distance to vectors in the indexed field.
* @return The next step in the knn predicate DSL.
*/
KnnPredicateOptionsStep matching(T vector);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.search.engine.search.predicate.dsl;

/**
* The step in a "match" predicate definition where the value to match can be set
* (see the superinterface {@link MatchPredicateMatchingStep}),
* or optional parameters for the last targeted field(s) can be set,
* or more target fields can be added.
*
* @param <S> The "self" type (the actual exposed type of this step).
* @param <N> The type of the next step.
* @param <T> The type of the match value.
* @param <V> The type representing the fields.
*/
public interface MatchPredicateFieldMoreGenericStep<
S extends MatchPredicateFieldMoreGenericStep<?, N, T, V>,
N extends MatchPredicateOptionsStep<?>,
T,
V>
extends MatchPredicateMatchingGenericStep<N, T>, MultiFieldPredicateFieldBoostStep<S> {

/**
* Target the given field in the match predicate,
* as an alternative to the already-targeted fields.
* <p>
* See {@link MatchPredicateFieldStep#field(String)} for more information about targeting fields.
*
* @param field The field with a <a href="SearchPredicateFactory.html#field-paths">path</a> to the index field
* to apply the predicate on.
* @return The next step.
*
* @see MatchPredicateFieldStep#field(String)
*/
S field(V field);

/**
* Target the given fields in the match predicate,
* as an alternative to the already-targeted fields.
* <p>
* See {@link MatchPredicateFieldStep#fields(String...)} for more information about targeting fields.
*
* @param fieldPaths The fields with <a href="SearchPredicateFactory.html#field-paths">paths</a> to the index fields
* to apply the predicate on.
* @return The next step.
*
* @see MatchPredicateFieldStep#fields(String...)
*/
S fields(V... fieldPaths);

}

0 comments on commit e5c26f9

Please sign in to comment.