Lance Leroy
Lance Leroy

Reputation: 399

ElasticSearch completion suggester with Java API

I had tried a few example codes on suggester feature of ElasticSearch on the net but I couldn't solve my problem against the autocomplete solution

my index:

client.prepareIndex("kodcucom", "article", "1")
      .setSource(putJsonDocument("ElasticSearch: Java",
        "ElasticSeach provides Java API, thus it executes all operations " +
        "asynchronously by using client object..",
         new Date(),
         new String[]{"elasticsearch"},
         "Hüseyin Akdoğan")).execute().actionGet();

and I used suggestbuilder to obtain the keyword then scan through the content "field", and here is where the null pointer exception occurs due to no result

CompletionSuggestionBuilder skillNameSuggest = new CompletionSuggestionBuilder("skillNameSuggest");

skillNameSuggest.text("lien");
skillNameSuggest.field("content");

SuggestRequestBuilder suggestRequestBuilder = client.prepareSuggest("kodcucom").addSuggestion(skillNameSuggest);

SuggestResponse suggestResponse = suggestRequestBuilder.execute().actionGet();

Iterator<? extends Suggest.Suggestion.Entry.Option> iterator =
          suggestResponse.getSuggest().getSuggestion("skillNameSuggest").iterator().next().getOptions().iterator();

Am I missing some filters or input criteria in order to get result? Any result should ok such as autocomplete or record found.

EDIT 1:

This is where I got the NPE and I could see that none of any result return at suggestResponse from debug mode

Iterator<? extends Suggest.Suggestion.Entry.Option> iterator =
              suggestResponse.getSuggest().getSuggestion("skillNameSuggest").iterator().next().getOptions().iterator();

EDIT 2: I am using 2.1.1 version of ElasticSearch Java API

EDIT 3: I tried in splitting up the iterator line into several code blocks, the NPE occur at the last line when converting a set of data into iterator, but there is not much helping

Suggest tempSuggest = suggestResponse.getSuggest();

Suggestion tempSuggestion = tempSuggest.getSuggestion("skillNameSuggest");

Iterator tempIterator = tempSuggestion.iterator();

I see that the codes:

SuggestRequestBuilder suggestRequestBuilder = client.prepareSuggest("kodcucom").addSuggestion(skillNameSuggest);

    SuggestResponse suggestResponse = suggestRequestBuilder.execute().actionGet();

has already consists a empty array/dataset, am I using the suggest request builder incorrectly?

Upvotes: 4

Views: 13202

Answers (2)

hakdogan
hakdogan

Reputation: 168

In order to use completion feature, you need to dedicate one field, which will be called completion and you have to specify a special mapping for it.

For example:

"mappings": {
   "article": {
     "properties": {
      "content": {
        "type": "string"
      },
     "completion_suggest": {
      "type": "completion"}
     }
   }
}

The completion_suggest field is the field we will use for the autocomplete function in the above code sample. After this mapping defination, the data must be indexing as follow:

curl -XPOST localhost:9200/kodcucom/article/1 -d '{
   "content": "elasticsearch",
   "completion_suggest": {
     "input": [ "es", "elastic", "elasticsearch" ],
     "output": "ElasticSearch"
   }
}'

Then Java API can be used as follows for get suggestions:

CompletionSuggestionBuilder skillNameSuggest  = new CompletionSuggestionBuilder("complete");
skillNameSuggest.text("es");
skillNameSuggest.field("completion_suggest");

SearchResponse searchResponse = client.prepareSearch("kodcucom")
        .setTypes("article")
        .setQuery(QueryBuilders.matchAllQuery())
        .addSuggestion(skillNameSuggest)
        .execute().actionGet();

CompletionSuggestion compSuggestion = searchResponse.getSuggest().getSuggestion("complete");

List<CompletionSuggestion.Entry> entryList = compSuggestion.getEntries();
if(entryList != null) {
    CompletionSuggestion.Entry entry = entryList.get(0);
    List<CompletionSuggestion.Entry.Option> options =entry.getOptions();
    if(options != null)  {
        CompletionSuggestion.Entry.Option option = options.get(0);
        System.out.println(option.getText().string());
    }
}

Upvotes: 4

Abhijith Anil
Abhijith Anil

Reputation: 119

Following link provides you the details of how to create a suggester index. https://www.elastic.co/blog/you-complete-me

Now, I use asynchronous Suggestionbuilder Java API to generate suggestions based on terms.

 SearchRequestBuilder suggestionsExtractor = elasticsearchService.suggestionsExtractor("yourIndexName", "yourIndexType//not necessary", "name_suggest", term);
        System.out.println(suggestionsExtractor);
        Map<String,Object> suggestionMap = new HashMap<>();
        suggestionsExtractor.execute(new ActionListener<SearchResponse>() {
            @Override
            public void onResponse(SearchResponse searchResponse) {
               if(searchResponse.status().equals(RestStatus.OK)) {
                   searchResponse.getSuggest().getSuggestion("productsearch").getEntries().forEach(e -> {
                       e.getOptions().forEach(s -> {
                           ArrayList<Object> contents = new ArrayList<>();

                           suggestionMap.put(s.getText().string(), s.getScore());

                       });
                   });


               }

            }

            @Override
            public void onFailure(Exception e) {
                Helper.sendErrorResponse(routingContext,new JsonObject().put("details","internal server error"));
                e.printStackTrace();
            }
        });

Following is how suggestionbuilder is created.

public SearchRequestBuilder suggestionsExtractor(String indexName, String typeName, String field, String term) {

        CompletionSuggestionBuilder csb = SuggestBuilders.completionSuggestion(field).text(term);
        SearchRequestBuilder suggestBuilder = client.prepareSearch()
                .suggest(new SuggestBuilder().addSuggestion(indexName, csb));
        return suggestBuilder;
    }

Upvotes: 1

Related Questions