Overriding default analyzer broken


I'm curious how to override the default analyzer and tokenizer via a template. I'm upgrading a plugin to be compatible with ES 5.0, and prior to the upgrade this template of ours wasn't giving any issues:
"order": 0,
"settings": {
"index.analysis.analyzer.fairhairIndexAnalyzerv3.alias": "default_index",
"index.analysis.analyzer.fairhairIndexAnalyzerv3.type": "fairhair-index-analyzer",
"index.analysis.analyzer.fairhairTokenizingAnalyzer.type": "fairhair-tokenizing-analyzer",
"index.analysis.analyzer.fairhairTokenizingAnalyzer.alias": "default_search"
"mappings": {
// mappings for types
// many types will have their analyzer set to fairhairIndexAnalyzerv2

But now with changes to make the plugin compatible with ES 5, when I make a bulk write request, I get the following error:
[2016-06-28 20:40:54,385][DEBUG][action.admin.indices.create] [Sleepwalker] [document.document-20151106] failed to create elasticsearch_1 | java.lang.IllegalStateException: already registered analyzer with name: default_search elasticsearch_1 | at org.elasticsearch.index.analysis.AnalysisService.<init>(AnalysisService.java:109) elasticsearch_1 | at org.elasticsearch.index.analysis.AnalysisRegistry.build(AnalysisRegistry.java:161)

I'm assuming this is because the template defines an alias for one of the analyzers as default_search. But what I don't understand is this: why is this error only coming up when I try to write data to ES? Are the templates not loaded when I initially PUT them to ES? Can I tell ES to override the default analyzer? Thanks again for your help!

Edit: I changed the "default_search" alias to a a non-reserved word, and I got the following error after trying to input data:
java.lang.IllegalArgumentException: setting [index.analysis.analyzer.default_index] is not supported anymore, use [index.analysis.analyzer.default] instead for index [document.document-20151106]

So after editing the the first setting in the template to have the value default, I then get the familiar error telling me there is already an analyzer with the name default.

Looking at the code for analysis service, I notice something a bit odd. In the constructor for the analysis service, it is passed a map of type Map<String, AnalyzerProvider> that I believe maps the names of the analyzers to the provider. The constructor immediately runs through a few checks to see if the map contains any of the keys "default", "default_search", "default_search_quoted." If there are no such keys, it will put in the default standard analyzer. But just a few more lines down, while iterating through the supplied entries in the analyzer provider map, we hit this bit of code:

if (analyzers.containsKey(name)) { // name is taken from each entry in map throw new IllegalStateException("already registered analyzer with name: " + name); }

How could we be triggering this if statement here, but we didn't hit the initial checks for "default" outside of the iteration?

EDIT 2: I found that the ES registers the standard analyzer as "default." So when trying to alias another analyzer as "default" it's impossible to get around hitting the Illegal State Exception. This makes me believe that it is an error to do the check in the Analysis Service to see if an analyzer has already been registered with a particular name. The check makes it impossible to register defaults!



can you open an issue on github for that for further discussion? Thanks!


It's already opened at https://github.com/elastic/elasticsearch/issues/19163

Thx, missed it. Corresponding PR is at https://github.com/elastic/elasticsearch/pull/19201