Multilingual fields

In some cases it may be required to store field values in multiple languages.

The following example defines a multilingual field title:

@Bean
List<FieldConfiguration> fieldConfigurations() {
    return Collections.singletonList(
        StandardFieldConfiguration.builder("title", ElasticsearchType.TEXT)
            .multilingual(true).build()
    );
}

Above FieldConfiguration results in the following Elasticsearch mapping:

{
  "picturesafe-search-sample-20200417-120220-687": {
    "mappings": {
      "properties": {
        "fulltext": {
          "type": "text"
        },
        "id": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword"
            }
          }
        },
        "title": {
          "properties": {
            "de": {
              "type": "text"
            },
            "en": {
              "type": "text"
            }
          }
        }
      }
    }
  }
}

To store field values in multiple languages, the ISO-639 language code suffix must be added to the field name, shown in the following example:

singleIndexElasticsearchService
    .addToIndex(DataChangeProcessingMode.BLOCKING, Arrays.asList(
    DocumentBuilder.id(1)
            .put("title.en", "This is an english test title")
            .put("title.de", "Dies ist ein deutscher Test-Titel").build(),
    DocumentBuilder.id(2)
            .put("title.en", "This is another english test title")
            .put("title.de", "Dies ist ein anderer deutscher Test-Titel").build()
));

Above example data results in following Elasticsearch index documents:

{
  "docs": [
    {
      "_index": "picturesafe-search-sample-20200417-121625-080",
      "_type": "_doc",
      "_id": "1",
      "_version": 1,
      "_seq_no": 0,
      "_primary_term": 1,
      "found": true,
      "_source": {
        "title.en": "This is an english test title",
        "id": "1",
        "title.de": "Dies ist ein deutscher Test-Titel"
      }
    },
    {
      "_index": "picturesafe-search-sample-20200417-121625-080",
      "_type": "_doc",
      "_id": "2",
      "_version": 1,
      "_seq_no": 1,
      "_primary_term": 1,
      "found": true,
      "_source": {
        "title.en": "This is another english test title",
        "id": "2",
        "title.de": "Dies ist ein anderer deutscher Test-Titel"
      }
    }
  ]
}

Multilingual fields can be searched via Expression in the same way as normal fields. The language variant to be searched for must be passed via SearchParameter:

SearchParameter searchParameter 
    = SearchParameter.builder().language("en").build();
Expression expression 
    = new ValueExpression("title", ValueExpression.Comparison.LIKE, "english");
 SearchResult searchResult 
    = singleIndexElasticsearchService.search(expression, searchParameter);

Supported languages

In the default configuration the languages German and English are predefined for multilingual fields. If other or additional languages are required, the FieldConfigurationProvider must be defined accordingly:

@Configuration
@ComponentScan(basePackages = {"de.picturesafe.search.elasticsearch"})
@Import({DefaultElasticConfiguration.class})
public class Config {

    // By default, the FieldConfigurationProvider defined in 
    // DefaultElasticConfiguration/DefaultIndexConfiguration supports 
    // German and English. If other languages are required, 
    // the FieldConfigurationProvider bean must be overwritten:
    @Bean
    @Primary
    FieldConfigurationProvider 
        fieldConfigurationProvider(IndexPresetConfiguration indexPresetConfiguration,
                                   List<FieldConfiguration> fieldConfigurations) {
    
        List<Locale> supportedLocales 
            = Arrays.asList(Locale.GERMAN, Locale.ENGLISH, Locale.FRENCH);
        
        Map<String, List<FieldConfiguration>> fieldConfigurationMap = new HashMap<>();
        fieldConfigurationMap.put(indexPresetConfiguration.getIndexAlias(), fieldConfigurations);
        StaticFieldConfigurationProvider fieldConfigurationProvider 
            = new StaticFieldConfigurationProvider(fieldConfigurationMap);
        fieldConfigurationProvider.setSupportedLocales(supportedLocales);
        return fieldConfigurationProvider;
    }

    @Bean
    List<FieldConfiguration> fieldConfigurations() {
        return Collections.singletonList(
            StandardFieldConfiguration.builder("title", ElasticsearchType.TEXT)
                .multilingual(true).build()
        );
    }
}

A multilingual search sample can be found here.