Skip to content

Default FieldType.Auto on Arrays of Objects #1803

Closed
@Stexxen

Description

@Stexxen

I'm not sure if this is by design or not, so appologies if it is.

If an array of Objects is not annotated with FieldType.Object the created mapping will ignore the FieldType annotations on the fields within that Object definition.

Here is some sample code that shows this.

@SpringBootApplication
@Import(EConfig.class)
public class Keyword implements CommandLineRunner {

  public static void main(String[] args) {
    SpringApplication.run(Keyword.class).close();
  }

  @Autowired
  ElasticScrollRepository repo;

  @Override
  public void run(String... args) throws Exception {
    repo.count();

    // State 1

    TestRecord testRecord =new TestRecord();
    testRecord.subRecordList2 = new ArrayList<>();
    SubRecord subRecord = new SubRecord();
    subRecord.subKeyword = "Key";
    subRecord.subString = "String";
    testRecord.subRecordList2.add(subRecord);
    repo.save(testRecord);

    // State 2
  }

}

@Configuration
@EnableElasticsearchRepositories(basePackageClasses = ElasticScrollRepository.class)
class EConfig extends AbstractElasticsearchConfiguration {

  @Override
  public RestHighLevelClient elasticsearchClient() {
    final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                                                            .connectedTo("localhost:9200")
                                                            .build();
    return RestClients.create(clientConfiguration).rest();
  }
}

@Repository
interface ElasticScrollRepository extends ElasticsearchRepository<TestRecord, String> {
}

@Document(indexName = "keyword_test")
class TestRecord {

  @Id
  public String id;

  @Field(name = "sub_record", type = FieldType.Object)
  public SubRecord subRecord;

  @Field(name = "sub_array_1", type = FieldType.Object)
  public List<SubRecord> subRecordList1;

  @Field(name = "sub_array_2")
  public List<SubRecord> subRecordList2;

}

class SubRecord {

  @Field(name = "sub_keyword", type = FieldType.Keyword)
  public String subKeyword;

  @Field(name = "sub_string", type = FieldType.Text)
  public String subString;

}

Within the TestRecord there are 3 fields

  @Field(name = "sub_record", type = FieldType.Object)
  public SubRecord subRecord;

  @Field(name = "sub_array_1", type = FieldType.Object)
  public List<SubRecord> subRecordList1;

  @Field(name = "sub_array_2")
  public List<SubRecord> subRecordList2;

During execution at // State 1 the created mapping looks like this

{
  "keyword_test" : {
    "mappings" : {
      "properties" : {
        "sub_array_1" : {
          "properties" : {
            "sub_keyword" : {
              "type" : "keyword"
            },
            "sub_string" : {
              "type" : "text"
            }
          }
        },
        "sub_record" : {
          "properties" : {
            "sub_keyword" : {
              "type" : "keyword"
            },
            "sub_string" : {
              "type" : "text"
            }
          }
        }
      }
    }
  }
}

Everything is ok, sub_array_1 and the fields are correctly defined as keywords where required. sub_array_2 is not defined in the mapping (maybe because of the default FieldType.Auto?)

Then at // State 2 we've added our first record. The mapping now looks like this

{
  "keyword_test" : {
    "mappings" : {
      "properties" : {
-- SNIP --
        "sub_array_1" : {
          "properties" : {
            "sub_keyword" : {
              "type" : "keyword"
            },
            "sub_string" : {
              "type" : "text"
            }
          }
        },
        "sub_array_2" : {
          "properties" : {
            "sub_keyword" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            },
            "sub_string" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            }
          }
        },
-- SNIP --
      }
    }
  }
}

You can see within sub_array_2 the fields sub_keyword and sub_string are both created with a text field and a keyword field as if they were defined as a MultiField

Is this the correct result? Which I think then means that all arrays of Objects must be annoted with a FieldType.Object to make the mapping creation correctly observe the annotations on any child fields.

I wasn't sure if this is as designed or not. We've now annotated all our Lists and arrays with FieldType.Object and recreated the index once we realised this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions