Я снова и снова сталкивался с одной и той же проблемой с отображениями на 6.4, и мне интересно, что я делал неправильно.
Я просто создаю отображение для добавления в индекс при его создании, но оно всегда нарушает мой тест с java.lang.IllegalStateException: Failed to close the XContentBuilder
Вот так я создаю объект XContentBuilder для своего отображения
public XContentBuilder buildIndexMapping() throws IOException{
XContentBuilder mapping = XContentFactory.jsonBuilder()
.startObject()
.startObject("_doc")
.startObject("_routing")
.field( "required", true )
.endObject()
.startObject( "properties" )
.startObject( "launchCode" )
.field( "type", "text" )
.endObject()
.startObject( "tenant_id" )
.field("type", "keyword")
.endObject()
.startObject( "environment_id" )
.field( "type", "keyword" )
.endObject()
.startObject("app_id")
.field( "type", "keyword" )
.startObject( "launch_id" )
.field( "type", "keyword" )
.endObject()
.startObject( "timestamp" )
.field( "type", "date" )
.endObject()
.startObject( "data" )
.startObject( "properties" )
.startObject( "changed" )
.field( "type", "boolean" )
.endObject()
.startObject( "census_groups" )
.field( "type", "object" )
.endObject()
.startObject( "local_member_id" )
.field( "type", "keyword" )
.endObject()
.startObject( "last_service_counter" )
.field( "type", "integer" )
.endObject()
.startObject( "last_election_counter" )
.field( "type", "integer" )
.endObject()
.startObject( "last_election_update_counter" )
.field( "type", "integer" )
.endObject()
.startObject( "last_membership_counter" )
.field( "type", "integer" )
.endObject()
.startObject( "last_service_config_counter" )
.field( "type", "integer" )
.endObject()
.startObject( "last_service_file_counter" )
.field( "type", "integer" )
.endObject()
.endObject() //properties
.endObject() //data
.endObject() //properties
.endObject() //doc
.endObject(); //root
return mapping;
}
И вот как я создаю запрос индекса.
public CreateIndexRequest buildIndexRequest( String indexType, List<String> tenantList ) throws IOException{
SimpleDateFormat format = new SimpleDateFormat( "yyyy-MM-dd" );
String date = format.format( new Date() );
String indexName = date + "-" + indexType;
CreateIndexRequest request = new CreateIndexRequest( indexName );
request.aliases( buildIndexAliases( tenantList, indexType ) );
request.settings( buildIndexSettings() );
request.mapping( "_doc", buildIndexMapping() ); //Test passes when commented out
return request;
}
И вот как я создаю индекс.
public CreateIndexResponse createIndex( CreateIndexRequest request ){
CreateIndexResponse response = null;
try{
L.info( "Requesting creation of the index" );
response = client.indices().create( request, RequestOptions.DEFAULT );
if( response.isAcknowledged() ){
L.info( "Index created" );
}
else{
L.warn( "Index not created: request not acknowledged" );
}
}
catch( IOException e ){
L.error( "Could not create Index" );
}
return response;
}
А это мой юнит-тест.
@Test
public void createIndexTest() {
try{
CreateIndexRequest request = client.buildIndexRequest( "census", this.tenantList );
CreateIndexResponse response = client.createIndex( request );
if (!response.isAcknowledged()) {
fail();
}
}
catch( IOException e ){
fail();
}
}
И это тело запроса индекса, которое успешно создает индекс с отображением при использовании PUT /index
через Почтальон.
{
"aliases": {
"census-tenant-a": {
"filter": {
"term": {
"_routing": "tenant-a"
}
},
"index_routing": "tenant-a",
"search_routing": "tenant-a"
},
"census-tenant-b": {
"filter": {
"term": {
"_routing": "tenant-b"
}
},
"index_routing": "tenant-b",
"search_routing": "tenant-b"
},
"census-tenant-c": {
"filter": {
"term": {
"_routing": "tenant-c"
}
},
"index_routing": "tenant-c",
"search_routing": "tenant-c"
}
},
"mappings": {
"_doc": {
"_routing": {
"required": true
},
"properties": {
"launch_code": {
"type": "text"
},
"tenant_id": {
"type": "keyword"
},
"environment_id": {
"type": "keyword"
},
"app_id": {
"type": "keyword"
},
"launch_id": {
"type": "keyword"
},
"timestamp": {
"type": "date"
},
"data": {
"properties": {
"changed": {
"type": "boolean"
},
"census_groups": {
"type": "object"
},
"local_member_id": {
"type": "keyword"
},
"last_service_counter": {
"type": "integer"
},
"last_election_counter": {
"type": "integer"
},
"last_election_update_counter": {
"type": "integer"
},
"last_membership_counter": {
"type": "integer"
},
"last_service_config_counter": {
"type": "integer"
},
"last_service_file_counter": {
"type": "integer"
}
}
}
}
}
},
"settings": {
"index": {
"number_of_shards": "3",
"number_of_replicas": "1"
}
}
}
Я действительно не могу понять, что происходит. Я знаю, что XContentBuilder
должен быть закрыт после использования, чтобы избежать утечек памяти.
Тем не менее, я хотел бы сначала создать индекс, а затем заняться закрытием ресурса.
Я использую ту же логику для создания псевдонимов и настроек, она не работает только с отображением.
Более того, как уже упоминалось, JSON-представление моего XContentBuilder
успешно выполняется, когда я использую Index API с PUT /index
.
Спасибо!