Skip to content

Commit

Permalink
HSEARCH-3909 Allow looking up available predicates/sorts/projections/…
Browse files Browse the repository at this point in the history
…aggregations for each field in the metamodel
  • Loading branch information
yrodiere committed Dec 14, 2023
1 parent d7e9595 commit 91a2df2
Show file tree
Hide file tree
Showing 42 changed files with 856 additions and 117 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,16 @@
package org.hibernate.search.backend.elasticsearch.search.predicate.impl;

import org.hibernate.search.backend.elasticsearch.types.predicate.impl.ElasticsearchSimpleQueryStringPredicateBuilderFieldState;
import org.hibernate.search.engine.backend.types.IndexFieldTraits;
import org.hibernate.search.engine.search.common.spi.SearchQueryElementTypeKey;

public final class ElasticsearchPredicateTypeKeys {

private ElasticsearchPredicateTypeKeys() {
}

private static <T> SearchQueryElementTypeKey<T> key(String name) {
return SearchQueryElementTypeKey.of( "predicate", name );
}

public static final SearchQueryElementTypeKey<
ElasticsearchSimpleQueryStringPredicateBuilderFieldState> SIMPLE_QUERY_STRING =
key( "simple-query-string" );
SearchQueryElementTypeKey.of( IndexFieldTraits.Predicates.SIMPLE_QUERY_STRING );

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/
package org.hibernate.search.backend.elasticsearch.search.projection.impl;

import static org.hibernate.search.engine.search.projection.spi.ProjectionTypeKeys.key;
import static org.hibernate.search.engine.search.common.spi.SearchQueryElementTypeKey.of;

import org.hibernate.search.engine.search.common.spi.SearchQueryElementTypeKey;

Expand All @@ -15,8 +15,8 @@ public final class ElasticsearchProjectionTypeKeys {
private ElasticsearchProjectionTypeKeys() {
}

public static final SearchQueryElementTypeKey<?> JSON_HIT = key( "json-hit" );
public static final SearchQueryElementTypeKey<?> SOURCE = key( "source" );
public static final SearchQueryElementTypeKey<?> EXPLANATION = key( "explanation" );
public static final SearchQueryElementTypeKey<?> JSON_HIT = of( "projection:json-hit" );
public static final SearchQueryElementTypeKey<?> SOURCE = of( "projection:source" );
public static final SearchQueryElementTypeKey<?> EXPLANATION = of( "projection:explanation" );

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* 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.backend.elasticsearch.types;

import org.hibernate.search.engine.backend.types.IndexFieldTraits;

/**
* Constants for the names of Elasticsearch-specific traits that can be exposed by index fields.
* <p>
* Currently empty, because there are no Elasticsearch-specific traits.
*
* @see IndexFieldTraits
*/
public final class ElasticsearchIndexFieldTraits {

private ElasticsearchIndexFieldTraits() {
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@
*/
package org.hibernate.search.backend.lucene.search.predicate.impl;

import static org.hibernate.search.engine.search.common.spi.SearchQueryElementTypeKey.of;

import org.hibernate.search.backend.lucene.types.predicate.impl.LuceneSimpleQueryStringPredicateBuilderFieldState;
import org.hibernate.search.engine.backend.types.IndexFieldTraits;
import org.hibernate.search.engine.search.common.spi.SearchQueryElementTypeKey;
import org.hibernate.search.engine.search.predicate.spi.PredicateTypeKeys;

public final class LucenePredicateTypeKeys {

private LucenePredicateTypeKeys() {
}

public static final SearchQueryElementTypeKey<LuceneSimpleQueryStringPredicateBuilderFieldState> SIMPLE_QUERY_STRING =
PredicateTypeKeys.key( "simple-query-string" );
of( IndexFieldTraits.Predicates.SIMPLE_QUERY_STRING );

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/
package org.hibernate.search.backend.lucene.search.projection.impl;

import static org.hibernate.search.engine.search.projection.spi.ProjectionTypeKeys.key;
import static org.hibernate.search.engine.search.common.spi.SearchQueryElementTypeKey.of;

import org.hibernate.search.engine.search.common.spi.SearchQueryElementTypeKey;

Expand All @@ -15,7 +15,7 @@ public final class LuceneProjectionTypeKeys {
private LuceneProjectionTypeKeys() {
}

public static final SearchQueryElementTypeKey<?> EXPLANATION = key( "explanation" );
public static final SearchQueryElementTypeKey<?> DOCUMENT = key( "document" );
public static final SearchQueryElementTypeKey<?> EXPLANATION = of( "projection:explanation" );
public static final SearchQueryElementTypeKey<?> DOCUMENT = of( "projection:document" );

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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.backend.lucene.types;

import org.hibernate.search.engine.backend.types.IndexFieldTraits;

/**
* Constants for the names of Lucene-specific traits that can be exposed by index fields.
* <p>
* Currently empty, because there are no Lucene-specific traits.
*
* @see IndexFieldTraits
*/
public final class LuceneIndexFieldTraits {

private LuceneIndexFieldTraits() {
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ is it searchable, sortable, projectable,
what is the expected java class for arguments to the <<search-dsl,Search DSL>>,
what are the analyzers/normalizer set on this field,
...
<9> Object fields can also be inspected.
<9> Inspect the "traits" of a field type:
each trait represents a predicate/sort/projection/aggregation
that can be used on fields of that type.
<10> Object fields can also be inspected.
====

[TIP]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
package org.hibernate.search.documentation.mapper.orm.indexedentities;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;

import java.sql.Date;
import java.util.Optional;
import java.util.Set;

import jakarta.persistence.EntityManagerFactory;

Expand All @@ -22,6 +24,7 @@
import org.hibernate.search.engine.backend.metamodel.IndexObjectFieldTypeDescriptor;
import org.hibernate.search.engine.backend.metamodel.IndexValueFieldDescriptor;
import org.hibernate.search.engine.backend.metamodel.IndexValueFieldTypeDescriptor;
import org.hibernate.search.engine.backend.types.IndexFieldTraits;
import org.hibernate.search.mapper.orm.Search;
import org.hibernate.search.mapper.orm.entity.SearchIndexedEntity;
import org.hibernate.search.mapper.orm.mapping.SearchMapping;
Expand Down Expand Up @@ -109,8 +112,26 @@ void indexMetamodel() {
assertThat( searchAnalyzerName ).isEmpty();
assertThat( normalizerName ).isEmpty();
//tag::indexMetamodel[]
Set<String> traits = type.traits(); // <9>
if ( traits.contains( IndexFieldTraits.Aggregations.RANGE ) ) {
// ...
//end::indexMetamodel[]
}
else {
fail( "The field should be aggregable!" );
//tag::indexMetamodel[]
}
//end::indexMetamodel[]
assertThat( traits ).contains(
IndexFieldTraits.Predicates.EXISTS,
IndexFieldTraits.Predicates.MATCH,
IndexFieldTraits.Predicates.RANGE,
IndexFieldTraits.Aggregations.TERMS,
IndexFieldTraits.Aggregations.RANGE
);
//tag::indexMetamodel[]
}
else if ( field.isObjectField() ) { // <9>
else if ( field.isObjectField() ) { // <10>
IndexObjectFieldDescriptor objectField = field.toObjectField();

IndexObjectFieldTypeDescriptor type = objectField.type();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@
package org.hibernate.search.engine.backend.document.model.spi;

import org.hibernate.search.engine.backend.common.spi.FieldPaths;
import org.hibernate.search.engine.backend.types.spi.AbstractIndexNodeType;
import org.hibernate.search.engine.common.tree.spi.TreeNodeInclusion;
import org.hibernate.search.engine.reporting.spi.EventContexts;
import org.hibernate.search.engine.search.common.spi.SearchIndexNodeTypeContext;
import org.hibernate.search.engine.search.common.spi.SearchIndexScope;
import org.hibernate.search.util.common.reporting.EventContext;

public abstract class AbstractIndexField<
S extends AbstractIndexField<S, SC, ?, C>,
SC extends SearchIndexScope<?>,
NT extends SearchIndexNodeTypeContext<SC, ? super S>,
NT extends AbstractIndexNodeType<SC, ? super S>,
C extends IndexCompositeNode<SC, ?, ?>>
extends AbstractIndexNode<S, SC, NT>
implements IndexField<SC, C> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ public interface IndexFieldDescriptor {
*/
IndexValueFieldDescriptor toValueField();

/**
* @return The type of this field, exposing its various capabilities.
* @see IndexFieldTypeDescriptor
*/
IndexFieldTypeDescriptor type();

/**
* @return The parent of this field, either the {@link IndexCompositeElementDescriptor#isRoot() index root}
* or an {@link IndexCompositeElementDescriptor#isObjectField() object field}.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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.backend.metamodel;

import java.util.Set;

import org.hibernate.search.engine.backend.types.IndexFieldTraits;

/**
* The type of a field in the index,
* exposing its various capabilities.
*
* @see IndexFieldDescriptor#type()
* @see IndexValueFieldTypeDescriptor
* @see IndexObjectFieldTypeDescriptor
*/
public interface IndexFieldTypeDescriptor {

/**
* @return An (unmodifiable) set of strings
* representing the {@link IndexFieldTraits field traits}
* enabled for fields of this type.
*/
Set<String> traits();

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
*
* @see IndexObjectFieldDescriptor
*/
public interface IndexObjectFieldTypeDescriptor {
public interface IndexObjectFieldTypeDescriptor extends IndexFieldTypeDescriptor {

/**
* @return {@code true} if this object field is represented internally as a nested document,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*
* @see IndexValueFieldDescriptor
*/
public interface IndexValueFieldTypeDescriptor {
public interface IndexValueFieldTypeDescriptor extends IndexFieldTypeDescriptor {

/**
* @return {@code true} if search predicates are supported on fields of this type.
Expand All @@ -25,7 +25,6 @@ public interface IndexValueFieldTypeDescriptor {
*/
boolean searchable();


/**
* @return {@code true} if sorts are supported on fields of this type.
* Some sorts may still be unsupported because they don't make sense
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* 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.backend.types;

/**
* Constants for the names of various traits that can be exposed by index fields.
* <p>
* Traits are a representation of what a field can be used for at search time:
* a particular predicate, sort, projections, aggregation...
* <p>
* See also backend-specific traits: {@code org.hibernate.search.backend.lucene.types.LuceneIndexFieldTraits},
* {@code org.hibernate.search.backend.elasticsearch.types.ElasticsearchIndexFieldTraits}.
*
* @see Predicates
* @see Sorts
* @see Projections
* @see Aggregations
*/
public final class IndexFieldTraits {

private IndexFieldTraits() {
}

/**
* Constants for the names of predicate-related traits that can be exposed by index fields.
*
* @see IndexFieldTraits
*/
public static class Predicates {

private Predicates() {
}

public static String named(String name) {
return "predicate:named:" + name;
}

public static final String EXISTS = "predicate:exists";
public static final String KNN = "predicate:knn";
public static final String MATCH = "predicate:match";
public static final String NESTED = "predicate:nested";
public static final String PHRASE = "predicate:phrase";
public static final String RANGE = "predicate:range";
public static final String REGEXP = "predicate:regexp";
public static final String SIMPLE_QUERY_STRING = "predicate:simple-query-string";
public static final String SPATIAL_WITHIN_BOUNDING_BOX = "predicate:spatial:within-bounding-box";
public static final String SPATIAL_WITHIN_CIRCLE = "predicate:spatial:within-circle";
public static final String SPATIAL_WITHIN_POLYGON = "predicate:spatial:within-polygon";
public static final String TERMS = "predicate:terms";
public static final String WILDCARD = "predicate:wildcard";

}

/**
* Constants for the names of sort-related traits that can be exposed by index fields.
*
* @see IndexFieldTraits
*/
public static class Sorts {

private Sorts() {
}

public static final String DISTANCE = "sort:distance";
public static final String FIELD = "sort:field";

}

/**
* Constants for the names of projection-related traits that can be exposed by index fields.
*
* @see IndexFieldTraits
*/
public static class Projections {

private Projections() {
}


public static final String DISTANCE = "projection:distance";
public static final String FIELD = "projection:field";
public static final String HIGHLIGHT = "projection:highlight";
public static final String OBJECT = "projection:object";

}

/**
* Constants for the names of aggregation-related traits that can be exposed by index fields.
*
* @see IndexFieldTraits
*/
public static class Aggregations {

private Aggregations() {
}

public static final String RANGE = "aggregation:range";
public static final String TERMS = "aggregation:terms";

}


}
Loading

0 comments on commit 91a2df2

Please sign in to comment.