Actually we want to search fields with keyword like in my case archetype.archetypeId.keyword="some search string" Note:This was implemented for exact match… is there any alternate solution for exact matching in hibernate search 6??
This was working fine in hibernate search 5 but not after migrating in hibernate search 6.
When I try to find out the root cause I see above index mapping difference.
How to implement hibernate search 5 behaviour for hibernate search 6 for archetype.archetypeId.keyword=“some search string”
The only way to get that exact behavior in Hibernate Search 6 would be to go full native: define your mapping as JSON, transform document data to JSON in the bridge, and define your search predicates as JSON in the Search DSL.
Alternatively, you could alter your bridge to give the keyword type to all your dynamic fields:
public class ResourceAttributesBinder implements PropertyBinder {
@Override
public void bind(PropertyBindingContext context) {
context.dependencies().useRootOnly();
PojoModelProperty bridgedElement = context.bridgedElement();
context.indexSchemaElement().fieldTemplate(
"attributeFieldValueTemplate_default",
- f -> f.asString().analyzer( "english" )
+ f -> f.asString()
.matchingPathGlob( "*.*" );
context.indexSchemaElement().objectFieldTemplate( "attributeObjectFieldTemplate_default" );
context.bridge(Map.class, new ResourceAttributesPropertyBridge());
}
}
Then don’t use archetype.archetypeId.keyword in your search queries, but just archetype.archetypeId.
And, last solution, if you need both full-text search and keyword search you could define two field templates in your binder:
public class ResourceAttributesBinder implements PropertyBinder {
@Override
public void bind(PropertyBindingContext context) {
context.dependencies().useRootOnly();
PojoModelProperty bridgedElement = context.bridgedElement();
+ context.indexSchemaElement().fieldTemplate(
+ "attributeFieldValueTemplate_keyword",
+ f -> f.asString()
+ .matchingPathGlob( "*.*_keyword" );
context.indexSchemaElement().fieldTemplate(
"attributeFieldValueTemplate_default",
f -> f.asString().analyzer( "english" )
.matchingPathGlob( "*.*" );
context.indexSchemaElement().objectFieldTemplate( "attributeObjectFieldTemplate_default" );
context.bridge(Map.class, new ResourceAttributesPropertyBridge());
}
}
And make sure to populate both fields in your bridge:
public class ResourceAttributesPropertyBridge implements PropertyBridge<Map> {
private final IndexObjectFieldReference fieldReference;
public ResourceAttributesPropertyBridge(IndexObjectFieldReference fieldReference) {
this.fieldReference = fieldReference;
}
@Override
public void write(DocumentElement target, Map bridgedElement, PropertyBridgeWriteContext context) {
System.out.println("######bridgedElement#######"+ bridgedElement);
final Map<String, Object> indexMap = (Map<String, Object>) bridgedElement;
if (!ObjectUtils.isEmpty(indexMap)) {
for (Map.Entry<String, Object> entry : indexMap.entrySet()) {
final List<String> attributeKeys = getIndexedAttributes().get(entry.getKey());
if (!ObjectUtils.isEmpty(attributeKeys)) {
final Map<String, Object> resourceAttributes = (Map<String, Object>)
DocumentElement attributesObject = target.addObject( entry.getKey() );
for (String attributeKey : attributeKeys) {
+ String attributeKeywordFieldName = attributeKey + "_keyword";
final Object attributeValue = resourceAttributes.get(attributeKey);
if (!ObjectUtils.isEmpty(attributeValue)) {
if (attributeValue instanceof List) {
((List<String>) attributeValue).forEach(item -> {
if (log.isTraceEnabled()) {
log.trace("Adding field {} with value {} to document.", fieldName, item);
}
attributesObject.addValue(attributeKey,item);
+ attributesObject.addValue(attributeKeywordFieldName,item);
});
} else {
if (log.isTraceEnabled()) {
log.trace("Adding field {} with value {} to document.", fieldName, attributeValue.toString());
}
attributesObject.addValue(attributeKey,item);
+ attributesObject.addValue(attributeKeywordFieldName,item);
}
}
}
}
}
}
}
}
Then don’t use archetype.archetypeId.keyword in your search queries, but archetype.archetypeId_keyword.
If we used this solution and tried to search like : archetype.archetypeId_keyword:spring-boot then getting same exception like
"errorCode": "Internal",
"errors": [
{
"message": "HSEARCH400611: Invalid type: 'archetype.archetypeId' is a value field, not an object field.",
"field": null,
"value": null
}
]
}