# How hiberante search creates index fields mapping?

**URL:** <https://discourse.hibernate.org/t/how-hiberante-search-creates-index-fields-mapping/6138>\
**Category:** Hibernate Search\
**Created:** [March 11, 2022, 4:22pm UTC](https://discourse.hibernate.org/t/how-hiberante-search-creates-index-fields-mapping/6138 "2022-03-11T16:22:38Z")\
**Posts on this page:** 1\
**Showing post:** 3

<div class="post-metadata">

**Author:** ![yrodiere](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/yrodiere/32/1760_2.png) [@yrodiere](https://discourse.hibernate.org/u/yrodiere)\
**Post date:** [March 14, 2022, 8:58am UTC](https://discourse.hibernate.org/t/how-hiberante-search-creates-index-fields-mapping/6138/3 "2022-03-14T08:58:19Z")

</div>

As I already told you in another post, Hibernate Search 5 did not create this mapping. Hibernate Search did not know about this field, so it didn’t add it to the Elasticsearch schema, and Elasticsearch [added it automatically the first time a document with that field was indexed](https://www.elastic.co/guide/en/elasticsearch/reference/current/dynamic-field-mapping.html):

> [@Error while searching with unavailable attribute in hibernate search](https://discourse.hibernate.org/t/error-while-searching-with-unavailable-attribute-in-hibernate-search/6115/8):
>
> Hibernate Search 5 was not very strict, it used to accept any field even if it didn’t know about it (and then it would behave strangely, which is why we stopped doing that in 6).  
> Also, Hibernate Search 5 would not handle dynamic fields explicitly, so most likely you were relying on Elasticsearch’s ability to automatically add fields it didn’t know about. And Elasticsearch adds a `keyword` sub-field by default in that case.

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:

```diff
 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:

```diff
 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:

```diff
 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`.

---

_[View the full topic](https://discourse.hibernate.org/t/how-hiberante-search-creates-index-fields-mapping/6138)._
