4

I'm playing with the current ES 2.3.4 from Java and it is silent on errors on my side. It's very difficult to track down the cause of problems.

QUESTION: How do I configure ES to be non-lenient, and fail early, instead of trying to do magic?


Case 1: creating an index with the Java API

A correct example is in the answers of Define custom ElasticSearch Analyzer using Java API and How to add analyzer settings in ElasticSearch?

Unfortunately I had an additional settings object around the analysis as in the question of the 2nd link.

Running the prepareCreate() doesn't mind, there's no error, just the acknowledgement.

Case 2: referencing an analyzer in a mapping that does not exist

In the same call to prepareCreate() I define my mappings. I define field("analyzer", "myanalyzer") which does not exist (since the boxing of objects was wrong) and again it does not mind.

The way I finally figured it out was by running a prepareSearch() with an explicit QueryBuilders.matchQuery("myfield", myvalue).analyzer("myanalyzer") and there it complained that there is no such analyzer.


Update 1

I'm still confused regarding the settings section. This example https://www.elastic.co/guide/en/elasticsearch/guide/current/ngrams-compound-words.html uses the settings section as a sibling of the mappings section, and does not directly start with the analysis section.

So I'm doing the same in Java and here is my exact code:

        xContentBuilder = XContentFactory.jsonBuilder().prettyPrint()
                .startObject() //root

                .startObject("settings")
                .startObject("analysis")
                .startObject("filter")
                .startObject("trigrams_filter").field("type", "ngram").field("min_gram", "3").field("max_gram", "3").endObject()
                .endObject() //filter
                .startObject("analyzer")
                .startObject("trigrams")
                    .field("type", "custom")
                    .field("tokenizer", "standard")
                    .field("filter", new String[]{"lowercase", "trigrams_filter"})
                .endObject()
                .endObject() //analyzer
                .endObject() //settings

                .startObject("mappings")
                .startObject(typeName)
                .startObject("properties")
                .startObject("myfield1").field("type", "string").field("analyzer", "trigrams").endObject()
                .endObject() //properties
                .endObject() //typeName
                .endObject() //mappings

                .endObject(); //root

I create the fresh index, and there is no failure callback, no abort:

    ListenableActionFuture<CreateIndexResponse> execute = this.node.client().admin().indices().prepareCreate(indexName)
            .setSettings(xContentBuilder)
            .execute();

    execute.addListener(new ActionListener<CreateIndexResponse>() {
        @Override
        public void onResponse(CreateIndexResponse createIndexResponse) {
            System.out.println(createIndexResponse);
        }

        @Override
        public void onFailure(Throwable e) {
            e.printStackTrace();
        }
    });

    CreateIndexResponse createIndexResponse = execute.actionGet();

Then I query, and this query goes through:

boolQuery.must(QueryBuilders.matchQuery("myfield1", parsedStreetName.getBase()));

Whereas this one does not:

boolQuery.must(QueryBuilders.matchQuery("myfield1", parsedStreetName.getBase()).analyzer("trigrams").minimumShouldMatch("40%"));

It says:

Caused by: [streetindex] QueryParsingException[[match] analyzer [trigrams] not found] at org.elasticsearch.index.query.MatchQueryParser.parse(MatchQueryParser.java:101)

If I leave out the settings start and end object then the trigrams analyzer gets created (search does not complain).

But:

  • how do I make it fail?
  • does the Java API differ here from the REST? Is that on purpose?
  • search does not find anything with the trigrams.

I can create other invalid configuration, and it happily creates the index. An example:

        xContentBuilder = XContentFactory.jsonBuilder().prettyPrint()
                .startObject() //root

                .startObject("asdf")
                .startObject("nana")
                .startObject("foobar").field("dada", "dudu").endObject()
                .endObject()
                .endObject()

                .endObject(); //root

I also had a missing endObject() once and the code did not throw.

I'm confused.

1
  • Regarding case 2, ES will not let you create an index by referencing an unknown analyzer in your mapping. Not sure how you're doing it, but you should show some code. Commented Aug 3, 2016 at 4:33

1 Answer 1

1

The correct Java API method for my use case is setSource(), not setSettings().

The Java code examples I had linked from SO only set settings, not also mappings at the same time. That's why those don't have the settings in the hierarchy.

The Javadoc of the setSource() method says:

Sets the settings and mappings as a single source.

So that's that. All clear now.

However, I really don't understand why the setSettings() accepts any kind of content.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.