Nest SuggestCompletion usage, throws 'is not a completion suggest field' exception

c#, elasticsearch, nest

Solution

UPDATE

You are try to create a property with the name "companyName.completion" but at that position its not valid and it will use the last token "completion". So its actually mapping a field called completion.... try changing the call to: `.Name(p => p.CompanyName)`

Other observations

You specify a mapping for the `Contact` but while indexing you use the `Person` and `Company` types.

In elasticsearch terms you mapped:

`/index/contact/`

but your documents are going into:

`/index/person/` and `/index/company`

NEST won't automatically map all implementation of a specific class and elasticsearch has no way of knowing the three are related.

I would refactor the mapping to a method and call it for all the types involved.

 var createResult = client.CreateIndex(indexName, index => index                
      .AddMapping<Contact>(tmd => MapContactCompletionFields(tmd))
      .AddMapping<Person>(tmd => MapContactCompletionFields(tmd))
      .AddMapping<Company>(tmd => MapContactCompletionFields(tmd))   
  );

 private RootObjectMappingDescriptor<TContact>  MapContactCompletionFields<TContact>(
      RootObjectMappingDescriptor<TContact> tmd)
      where TContact : Contact
 {
      return  tmd.Properties(props => props
           .Completion(s => s
                .Name(p => p.CompanyName.Suffix("completion"))
                .IndexAnalyzer("standard")
                .SearchAnalyzer("standard")
                .MaxInputLength(20)
                .Payloads()
                .PreservePositionIncrements()
                .PreserveSeparators()
           )                        
       );
 } 

That method returns the descriptor so you can further chain on it.

Then when you do a search for contacts:

var result = getElasticClientInstance("contacts").Search<Contact>(
    body => descriptor
        .Types(typeof(Person), typeof(Company))
);

That types hint will cause the search to looking `/index/person` and `/index/company` and will know how to give you back a covariant list of documents.

So you can do `result.Documents.OfType<Person>()` after the previous call.

Problem

I'm a complete beginner to elasticsearch and I have been trying to use elasticsearch's completion suggester using Nest for auto-complete on a property. Here is my mapping (as mentioned here: ): ``` var createResult = client.CreateIndex(indexName, index => index .AddMapping<Contact>(tmd => tmd .Properties(props => props .Completion(s => s.Name(p => p.CompanyName.Suffix("completion")) .IndexAnalyzer("standard") .SearchAnalyzer("standard") .MaxInputLength(20) .Payloads() .PreservePositionIncrements() .PreserveSeparators()) ) ) ); var resultPerson = client.IndexMany(documents.OfType<Person>(), new SimpleBulkParameters { Refresh = true }); var resultCompany = client.IndexMany(documents.OfType<Company>(), new SimpleBulkParameters { Refresh = true }); ``` And while indexing I'm just making use of `IndexMany` method and passing the `IEnumerable<Contact>` (Contact has a property by name CompanyName, Contact is an abstract class, both Person and Company are concrete implementations of it). The search throws an exception saying ElasticSearchException[Field [companyName] is not a completion suggest field] And the query looks like below: ``` SearchDescriptor<Contact> descriptor = new SearchDescriptor<Contact>(); descriptor = descriptor.SuggestCompletion("suggest", c => c.OnField(f => f.CompanyName).Text(q)); var result = getElasticClientInstance("contacts").Search<Contact>(body => descriptor); string qe = result.ConnectionStatus.ToString(); ``` What am I doing wrong here, I looked into Nest's tests on `SuggestCompletion` but not much help, meaning the test only depict on how to get suggestions but not on how to set index mappings for SuggestCompletion. I also tried setting up `edgeNgram` tokenizer as mentioned in this post but, couldn't proceed there as well. Any direction or an example on how to proceed would greatly help.

Original source

Related problems