Search code examples
javaelasticsearchspring-data-elasticsearch

How to store java enums using spring-data-elasticsearch


public enum Smoking {
    NO("No"),YES("Yes");
}

How to store java enums using spring-data-elasticsearch, I want to store Yes, No and search for the same


Solution

  • You can do so by providing custom converters for your Enum to convert it from and to a String. I suppose you want to have this property as a keyword in Elasticsearch and not analyzed.

    Here is an implementation of the Smoking enum where I have added the necessary converters as nested enums (I prefer to use the enum as singleton implementation for converters):

    import org.springframework.core.convert.converter.Converter;
    import org.springframework.data.convert.ReadingConverter;
    import org.springframework.data.convert.WritingConverter;
    
    public enum Smoking {
        YES("yes"),
        NO("No");
    
        private String elasticsearchName;
    
        Smoking(String elasticsearchName) {
            this.elasticsearchName = elasticsearchName;
        }
    
        @WritingConverter
        public enum SmokingToStringConverter implements Converter<Smoking, String> {
    
            INSTANCE;
    
            @Override
            public String convert(Smoking source) {
                return source.elasticsearchName;
            }
        }
    
        @ReadingConverter
        public enum StringToSmokingConverter implements Converter<String, Smoking> {
    
            INSTANCE;
    
            @Override
            public Smoking convert(String source) {
                for (Smoking smoking : Smoking.values()) {
                    if (smoking.elasticsearchName.equals(source)) {
                        return smoking;
                    }
                }
                return null;
            }
        }
    }
    

    The converters need to be registered, this can be done in the configuration class (see the documentation about configuring the client at https://docs.spring.io/spring-data/elasticsearch/docs/4.0.4.RELEASE/reference/html/#elasticsearch.clients.rest) by adding a custom implementation of elasticsearchCustomConversions():

    @Override
    public ElasticsearchCustomConversions elasticsearchCustomConversions() {
        return new ElasticsearchCustomConversions(Arrays.asList(
            Smoking.SmokingToStringConverter.INSTANCE,
            Smoking.StringToSmokingConverter.INSTANCE)
        );
    }
    

    You then would use your enum class in your entity:

    @Field(type = FieldType.Keyword)
    private Smoking smoking;
    

    That's all, the enum values are stored in Elasticsearch in the desired form.