Search code examples
elasticsearchhibernate-searchaws-elasticsearchelasticsearch-analyzers

Hibernate search and elasticsearch: mapper_parsing_exception + analyzer [...] not found for field [...]


I'm using hibernate search to automatically create indexes for a specific entity

@Entity
@Indexed
public class Entity extends BaseEntity {

    private static final long serialVersionUID = -6465422564073923433L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    @Field(bridge = @FieldBridge(impl = PropertyFieldBridge.class))
    private List<PropertyValue> properties = new ArrayList<>(); // PropertyValue is an abstract

}

The field bridge is creating the string fields with the format: pt_[a-zA-Z0-9]+_i18n.

And after that i'm creating a dynamic template to deal with translated fields:

PUT {{elasticsearch}}/com.orm.entity.entity.entity/com.orm.entity.entity.Entity/_mapping
{
  "com.gamila.api.orm.entity.entity.Entity": {
    "dynamic_templates": [
      {
        "my_analyzer": {
          "match_mapping_type": "string",
          "match_pattern": "regex",
          "match": "^pt_[a-zA-Z0-9]+_i18n",
          "mapping": {
            "type": "text",
            "analyzer": "portugueseAnalyzer"
          }
        }
      }
    ]
  }
}

But when i'm creating an entity it always returns an error:

Response: 400 'Bad Request' with body 
{
  "error": {
    "root_cause": [
      {
        "type": "mapper_parsing_exception",
        "reason": "analyzer [portugueseAnalyzer] not found for field [pt_name_i18n]"
      }
    ],
    "type": "mapper_parsing_exception",
    "reason": "analyzer [portugueseAnalyzer] not found for field [pt_name_i18n]"
  },
  "status": 400
}

The portugueseAnalyser is defined through:

public class Analyzer implements ElasticsearchAnalysisDefinitionProvider {

    @Override
    public void register(ElasticsearchAnalysisDefinitionRegistryBuilder builder) {
        builder.analyzer("portugueseAnalyzer")
                .withTokenizer("standard")
                .withTokenFilters("lowercase", "portugueseStemmer", "portugueseStop", "edge_ngram_3");

        builder.tokenFilter("portugueseStemmer")
                .type("stemmer").param("language", "portuguese");
        builder.tokenFilter("portugueseStop")
                .type("stop").param("stopwords", "_portuguese_");
    }

}

Can somebody tell me what i'm doing wrong? I've already skim through some questions here in stackoverflow without success.

PS: i'm using elasticsearch (5.6) from AWS

Thanks in advance


Solution

  • When Hibernate Search 5 pushes the mapping to Elasticsearch, it will only include analyzer definitions for analyzers that are actually used somewhere in the mapping. In your case, the analyzer is not used as far as Hibernate Search is concerned, so it is ignored.

    As a workaround in Hibernate Search 5, you can declare a dummy field that uses your analyzer, but will never be populated. You can find an example of how to do that here.