Unable to add @PropertyBinding on a field, which is in includepath or other object

Unable to add @PropertyBinding on a field, which is in includepath or other object
and unable to user criteria “caseKind.translations.en”

This is my mapping as below :

@Indexed @Table(name="dcase", schema="test") public class Case extends VersioningEntity { @IndexedEmbedded(includePaths = {"id", "translations"}) @IndexingDependency(reindexOnUpdate = ReindexOnUpdate.SHALLOW) @ManyToOne @JoinColumn(name="case_kind_type_id") private CaseKindType caseKind; } @Entity @Table(name="case_kind_type", schema="test") public class CaseKindType extends Localisable implements Serializable { @OneToMany @JoinColumn(name="`key`", referencedColumnName="case_kind_name") @GenericField(projectable = Projectable.YES) @PropertyBinding(binder = @PropertyBinderRef(type = I18FieldBinder.class)) private Set<Translation> translations;	} 

The above mapping throwing error as below:

 Hibernate ORM mapping: type 'com.eurodyn.eips.core.db.entity.Case': path '.caseKind<no value extractors>.translations': failures: - HSEARCH000135: No default value bridge implementation for type 'com.eurodyn.eips.core.db.entity.Translation'. Use a custom bridge. 

I want to search sort or search data with criteria “caseKind.translations.en” here we have translation with multiple language code like “en,nl,fr”

earlier I am using Valuebridge as below which is not working with above criteria:

@GenericField(projectable = Projectable.YES, valueBridge = @ValueBridgeRef(type = I18FieldBridge.class)) public class I18FieldBridge implements ValueBridge<Translation, String> {	@Override	public String toIndexedValue(Translation translation, ValueBridgeToIndexedValueContext context) {	return translation == null ? null : translation.getDescription() + "." + translation.getLanguageCode();	} } 

it is storing data as
translations:
{
1: “data.en”
2: “data.nl”
3: “data.fr
}

I think I need to store data as below to use criteria “caseKind.translations.en” :
translations:
{
en: “data”
nl: “data”
fr: “data”
}

Please help me to achive it.

These two annotations are duplicates. If you’re using @PropertyBinding, you don’t need @GenericField (which in this case cannot work and is triggering the error).

Remove @GenericField, that should get you one step further.

And if things still don’t work, please provide your code, including the property brige/binder.

EDIT: We’ll need the code of Translation too.

1 Like

Thank you for your suggestion, now I am step a ahead.

My translation entity as below :

@Entity @Table(name = "translation", schema = "translation",	uniqueConstraints=@UniqueConstraint(columnNames={"`key`", "lang_code"})) @EntityListeners(EntityInterceptor.class) public class Translation implements Translationable, Serializable {	private static final long serialVersionUID = -7906256457718143365L;	@Id	@GeneratedValue(strategy=GenerationType.IDENTITY)	@Column(name="id", unique=true, nullable=false, updatable=false)	private Long id;	@Column(name="`key`", length=100, nullable=false, updatable=false)	private String key;	@Column(name="description", columnDefinition="nvarchar", length=300, nullable=false, updatable=false)	private String description;	@Column(name="lang_code", columnDefinition="bpchar", length=2, nullable=false, updatable=false)	private String languageCode; } 

My Binder and Bridge as below :

public class I18FieldBinder implements PropertyBinder {	@Override public void bind(PropertyBindingContext context) { context.dependencies().useRootOnly(); PojoModelProperty bridgedElement = context.bridgedElement(); IndexSchemaObjectField attributeField = context.indexSchemaElement() .objectField( bridgedElement.name() ); context.bridge(Set.class,new I18FieldTestBridge(attributeField.toReference())); } } public class I18FieldTestBridge implements PropertyBridge<Set> { private final IndexObjectFieldReference fieldReference; public I18FieldTestBridge(IndexObjectFieldReference fieldReference) { this.fieldReference = fieldReference; } @SuppressWarnings("unchecked")	@Override public void write(DocumentElement target, Set bridgedElement, PropertyBridgeWriteContext context) {	final Set<Translation> translations = (Set<Translation>) bridgedElement; DocumentElement indexedAttributeMetadata = target.addObject( fieldReference );	for (Translation translation : translations) { final String fieldName = translation.getLanguageCode(); indexedAttributeMetadata.addValue(fieldName,translation.getDescription()); } } } 

In above code I updated proper Binder class name as below :

 @PropertyBinding(binder = @PropertyBinderRef(type = I18FieldBinder.class)) 

After your suggestion I run the code , now I am getting error as below in I18FieldTestBridge.write :

Caused by: org.hibernate.search.util.common.SearchException: HSEARCH400609: Unknown field 'caseKind.translations.lb'. 

You declared an object field, but you didn’t declare the fields within that object field. You need one field per language, e.g. lb, en, fr, es, …

Just see the examples in the docs and how it declares the object field and then fields within it:

 IndexSchemaObjectField summaryField = context.indexSchemaElement() .objectField( "summary" ); IndexFieldType<BigDecimal> amountFieldType = context.typeFactory() .asBigDecimal().decimalScale( 2 ).toIndexFieldType(); context.bridge( List.class, new Bridge( summaryField.toReference(), summaryField.field( "total", amountFieldType ).toReference(), summaryField.field( "books", amountFieldType ).toReference(), summaryField.field( "shipping", amountFieldType ).toReference() ) ); 

After your suggestion, I updated My binder and Bridge as below :

public class I18FieldBinder implements PropertyBinder {	@Override public void bind(PropertyBindingContext context) { context.dependencies().useRootOnly(); PojoModelProperty bridgedElement = context.bridgedElement(); IndexFieldType<String> nameType = context.typeFactory() .asString() .toIndexFieldType(); IndexSchemaObjectField attributeField = context.indexSchemaElement().objectField(bridgedElement.name()); context.bridge(Set.class,new I18FieldTestBridge(	attributeField.toReference(),	attributeField.field("en", nameType).toReference(),	attributeField.field("de",nameType).toReference(),	attributeField.field("fr",nameType).toReference(),	attributeField.field("lb",nameType).toReference()	)); } } @SuppressWarnings("rawtypes") public class I18FieldTestBridge implements PropertyBridge<Set> {	private final IndexObjectFieldReference fieldReference;	private final IndexFieldReference<String> en_Field;	private final IndexFieldReference<String> de_Field;	private final IndexFieldReference<String> fr_Field;	private final IndexFieldReference<String> lb_Field; public I18FieldTestBridge(IndexObjectFieldReference fieldReference,IndexFieldReference<String> en_Field,	IndexFieldReference<String> de_Field,IndexFieldReference<String> fr_Field,	IndexFieldReference<String> lb_Field) {	this.fieldReference = fieldReference;	this.en_Field = en_Field;	this.de_Field = de_Field;	this.fr_Field = fr_Field;	this.lb_Field = lb_Field;	}	@SuppressWarnings("unchecked")	@Override	public void write(DocumentElement target, Set bridgedElement, PropertyBridgeWriteContext context) {	Set<Translation> translations = bridgedElement; String english = ""; String german = ""; String french = ""; String luxumberg = "";	for (Translation translation : translations) {	String description = translation.getDescription();	switch ( translation.getLanguageCode() ) { case "en": english = description; break; case "de": german = description; case "fr": french = description; break; case "lb": luxumberg = description; break;	}	}	DocumentElement indexedAttributeMetadata = target.addObject( fieldReference );	indexedAttributeMetadata.addValue(this.en_Field, english);	indexedAttributeMetadata.addValue(this.de_Field, german);	indexedAttributeMetadata.addValue(this.fr_Field, french);	indexedAttributeMetadata.addValue(this.lb_Field, luxumberg);	} } 

But unfortunately it is not returning in ES document, for your info
fieldReference coming as ‘ElasticsearchIndexObjectFieldReference[absolutePath=caseKind.translations]’
but result coming it is coming empty :

you can check my mapping too :

I want to add data in side translations: object like
en: description
nl: description

can you please guide further .

Thank you

This looks like the binder and bridge are getting ignored, which is odd.

You did leave the @PropertyBinding annotation, right?

After you made your changes to the code:

  1. Did you recreate the schema?
  2. Did you trigger reindexing?

Also, probably not the cause of your trouble, but you bypassed dependency detection completely here:

Note this means Hibernate Search will not know that an update to e.g. Translation#description requires reindexing, and as a result it will not reindex properly.

To get proper automatic reindexing, define dependencies correctly: Hibernate Search 7.2.2.Final: Reference Documentation

Hi,
I am using @PropertyBinding

After I made changes to the code:

  1. should I recreate schema what you meant ?
    I redeployed and it’s trigger binding , then I re indexed, it is triggered Bridge
    I already getting proper values but it is not generating tree as I asked and shown below
attributeField = casekind.transaltions 

as I shown you image , inside translations { } I want to create

caseKind: id: 101 trnslations : { en: english lb: luxemburg fr: french } 
  1. Yes I did reindex but it is not writenniing in index as above.

can you please guide me how to reach casekind.translations to add new field in that array , then value

Thank you

Yes, after you change your mapping to add new fields, you should recreate your schema.
See the link I provided: Hibernate Search 7.2.2.Final: Reference Documentation

Good. You need to make sure you recreate the schema first, though; see above.

I understand this.

I’m afraid I cannot, at least not with this information. Your bridge looks good, so either I’m missing something, or the problem must be elsewhere.

For further help, I will need a minimal reproducer, i.e. a small project on GitHub showing the problem, that I can run on my computer and debug. You can start from this: hibernate-test-case-templates/search/hibernate-search-7/orm-elasticsearch at main · hibernate/hibernate-test-case-templates · GitHub

Hello ,

Finally achieved it , missed below line

 // ADD THIS attributeField.fieldTemplate( "attributeFieldValueTemplate_default", f -> f.asString().analyzer( "english" ) ); 

Which found here https://discourse.hibernate.org/t/hsearch400609-unknown-field-attributes-someattributename/6114/4
it is mentioned by you only . :grinning:

Thank you for your guide and support

This shouldn’t be necessary if you declare your fields statically with attributeField.field("en", nameType).toReference(), but okay. Glad you found a solution!