In my domain model a "Product" object has a "Map<String, ProductDescription> descriptions" property which stores localized product descriptions.
The key of the map is the iso3 language code.
The value of the map is an instance of ProductDescription which holds a "localeCode" String field (same as the iso3 map key above) and a "value" String field.
So for example myProduct.getDescriptions().get("eng").getValue() returns the english description of the product.
I need to be able to query product descriptions in the language of the user.
My first attempt used @IndexedEmbedded on the "descriptions" field of Product, and @Field on the "localeCode" and "value" fields of ProductDescription.
This worked almost fine, because I could query for a product by using the "descriptions.localeCode" and "descriptions.value" fields.
The problem was that I couldn't query for a specific localeCode-value couple, so I ended up with Products matching a description in the wrong language.
My last attempt is using a FieldBridge to convert the "descriptions" field to a fileld that contains the localeCode in the name, so I get the fields "descriptions.eng", "descriptions.ita" etc.
Everything looks fine through Luke, but when I query for "descriptions.eng" I get a SearchException: "Unable to find field descriptions.eng in com.my.entity.Product".
I'm using Hibernate Search 3.4.2.Final on Hibernate Core 3.6.0 and Lucene Core 3.1.0
Is there a way to achieve my goal?
Some simplified code snippets
Code:
@Indexed
@Entity
public class Product {
...
@Field
@FieldBridge(impl = ProductDescriptionMapBridge.class)
@OneToMany(cascade=CascadeType.ALL, orphanRemoval=true)
@JoinColumn(name="Product_id")
@MapKey(name="localeCode")
protected Map<String, ProductDescription> getDescriptions() {
return descriptions;
}
}
@Entity
public class ProductDescription {
...
public String getLocaleCode() {
return localeCode; // iso3 language code
}
public String getValue() {
return value; // localized description
}
}
public class ProductDescriptionMapBridge implements FieldBridge {
public void set(String fieldName, Object fieldValue, Document document, LuceneOptions luceneOptions) {
Map<String, ProductDescription> productDescriptionMap = (Map<String, ProductDescription>) fieldValue;
for (String localeCode : productDescriptionMap.keySet()) {
luceneOptions.addFieldToDocument(
fieldName + "." + localeCode,
productDescriptionMap.get(localeCode).getValue(),
document);
}
}
}
The query:
Code:
Transaction tx = fullTextSession.beginTransaction();
QueryBuilder queryBuilder = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Product.class).get();
org.apache.lucene.search.Query query = queryBuilder.keyword()
.onFields("descriptions.eng")
.matching("quick brown fox")
.createQuery();
org.hibernate.Query hibQuery = fullTextSession.createFullTextQuery(query, Product.class);
result = hibQuery.list();
tx.commit();
The exception:
Code:
org.hibernate.search.SearchException: Unable to find field descriptions.eng in com.my.entity.Product
at org.hibernate.search.engine.DocumentBuilderIndexedEntity.objectToString(DocumentBuilderIndexedEntity.java:688) ~[hibernate-search-3.4.2.Final.jar:3.4.2.Final]
at org.hibernate.search.query.dsl.impl.ConnectedMultiFieldsTermQueryBuilder.buildSearchTerm(ConnectedMultiFieldsTermQueryBuilder.java:138) ~[hibernate-search-3.4.2.Final.jar:3.4.2.Final]
at org.hibernate.search.query.dsl.impl.ConnectedMultiFieldsTermQueryBuilder.createQuery(ConnectedMultiFieldsTermQueryBuilder.java:92) ~[hibernate-search-3.4.2.Final.jar:3.4.2.Final]
at org.hibernate.search.query.dsl.impl.ConnectedMultiFieldsTermQueryBuilder.createQuery(ConnectedMultiFieldsTermQueryBuilder.java:73) ~[hibernate-search-3.4.2.Final.jar:3.4.2.Final]
at com.my.cms.action.admin.SearchAction.test(SearchAction.java:61) ~[SearchAction.class:na]
Thank you.