-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Updating index mapping automatically #2465
Comments
I added my own initializer for this: /**
* Initializes Elasticsearch by updating index mappings.
*/
@Component
class MappingInitializer
{
private static final Logger LOG = LogManager.getFormatterLogger(MappingInitializer.class);
private final ElasticsearchOperations operations;
@Autowired
MappingInitializer(ElasticsearchOperations operations)
{
this.operations = requireNonNull(operations);
}
/**
* Initializes the Elasticsearch features.
*/
@PostConstruct
public void initialize()
{
IndexOperations indexOperations = operations.indexOps(MyDocumentType.class);
boolean result = indexOperations.putMapping();
LOG.info("Mapping update result: " + result);
}
} But it feels like it could be a nice thing to have natively in Spring Data Elasticsearch. Like |
Related side note: I can't find any way of managing custom analyzers (or other index settings). Could be nice to have that possibility, on I tried messing around with
|
PS: Sorry for the spam! Okay, so the exception above is not related to Spring really, as can be seen here: elastic/elasticsearch-java#392. To make sure the index settings and mappings is up to date, I've written a custom initializer component: /**
* Creates and updates the Elasticsearch indices, their settings and their mappings.
*/
@Component
class IndexInitializer
{
private static final Logger LOG = LogManager.getLogger(IndexInitializer.class);
private final ElasticsearchOperations operations;
@Autowired
IndexInitializer(ElasticsearchOperations operations)
{
this.operations = requireNonNull(operations);
}
/**
* Initializes the Elasticsearch features.
*/
@PostConstruct
public void initialize()
{
initializeIndex(MyDocumentClass.class);
}
private void initializeIndex(Class<?> type)
{
IndicesTemplate indexOperations = (IndicesTemplate) operations.indexOps(type);
String indexName = indexOperations.getIndexCoordinates().getIndexName();
if (!indexOperations.exists())
{
LOG.info("Creating index '{}'", indexName);
assertAcknowledged(indexOperations.execute(client -> client.create(new CreateIndexRequest.Builder()
.index(indexName)
.settings(indexSettings(true))
.build())));
}
else
{
LOG.info("Getting index settings for '{}' to check if we need to update them", indexName);
IndexSettings settings = indexOperations.execute(client -> client.getSettings()).get(indexName).settings();
if (areSettingsEqual(settings, indexSettings(false)))
{
LOG.info("No need to update index settings for index '{}'", indexName);
}
else
{
LOG.warn("Closing index '{}' in order to update its settings", indexName);
assertAcknowledged(indexOperations.execute(client -> client.close(new CloseIndexRequest.Builder().index(indexName).build())));
LOG.warn("Updating settings of index '{}'", indexName);
assertAcknowledged(indexOperations.execute(client -> client.putSettings(new PutIndicesSettingsRequest.Builder().settings(indexSettings(false)).build())));
LOG.warn("Re-opening index '{}'", indexName);
assertAcknowledged(indexOperations.execute(client -> client.open(new OpenRequest.Builder().index(indexName).build())));
}
}
LOG.info("Updating the mapping of index '{}'", indexName);
if (indexOperations.putMapping())
{
LOG.info("Successfully updated the mapping of index '{}'", indexName);
}
else
{
LOG.warn("Could not update the mapping for index '{}'", indexName);
}
}
private IndexSettings indexSettings(boolean create)
{
Builder settings = new IndexSettings.Builder();
if (create)
{
settings.numberOfShards("1");
}
settings.numberOfReplicas("0");
settings.analysis(new IndexSettingsAnalysis.Builder()
.analyzer("html-content", new Analyzer.Builder()
.custom(new CustomAnalyzer.Builder()
.tokenizer("standard")
.charFilter("html_strip")
.build())
.build())
.build());
return new IndexSettings.Builder()
.index(settings.build())
.build();
}
// TODO: Make this check smarter... Elastics objects do not implement #equals properly, so it's a bit tricky...
private boolean areSettingsEqual(IndexSettings left, IndexSettings right)
{
IndexSettings l = left.index();
IndexSettings r = right.index();
return l.numberOfReplicas().equals(r.numberOfReplicas())
&& l.analysis().analyzer().keySet().equals(r.analysis().analyzer().keySet());
}
private void assertAcknowledged(AcknowledgedResponse response)
{
if (!response.acknowledged())
{
throw new IllegalStateException("Response from Elasticsearch was not acknowledged");
}
}
} Some thoughts though:
|
|
|
Creating indexes works perfectly, a very nice feature IMO. But whenever I make changes to my document classes, for example adding a new field, I need to update the index mapping. It would be awesome if I could tell Spring Boot Elasticsearch to perform this update automatically, just like index creation works.
Thoughts? Maybe this feature already exists, but I just can't seem to find it?
The text was updated successfully, but these errors were encountered: