I am using the Nest client against Elasticsearch. I am using an n-gram index analyzer. I am noticing some odd behavior - when I search for words from the beginning I am not getting any results. However, if I search from the second character on, it works perfectly. These are just normal English letters.
So, for instance, it will find words containing 'kitty' if I search for 'itty', 'itt', 'tty', etc. but not 'ki', 'kit', etc. It's almost like n-gram is just skipping over the first character.
I am not sure if this is being caused by Nest or if this is normal behavior for n-gram. My index settings look similar to those found in this post: Elasticsearch using NEST: How to configure analyzers to find partial words? except my max-gram is only 10.
Update
I simplified my code a little bit and verified the same behavior.
Here is the mapping configuration defined using Nest:
const string index = "myApp";
const string type = "account";
const string indexAnalyzer = "custom_ngram_analyser";
const string searchAnalyzer = "standard";
const string tokenizer = "custom_ngram_tokenizer";
const string tokenFilter = "custom_ngram_tokenFilter";
...
client.CreateIndex(index, i => i
.Analysis(ad => ad
.Analyzers(a => a.Add(indexAnalyzer, new CustomAnalyzer() { Tokenizer = tokenizer }))
.Tokenizers(t => t.Add(tokenizer, new NGramTokenizer() { MinGram = 1, MaxGram = 15 }))
.TokenFilters(f => f.Add(tokenFilter, new NgramTokenFilter() { MinGram = 1, MaxGram = 15 })))
.TypeName(account);
.IdField(r => r.SetPath("accountId").SetIndex("not_analyzed").SetStored(true));
.Properties(ps => ps.Number(p => p.Name(r => r.AccountId)
.Index(NonStringIndexOption.not_analyzed)
.Store(true));
.String(p => p.Name(r => r.AccountName)
.Index(FieldIndexOption.analyzed)
.IndexAnalyzer(indexAnalyzer)
.SearchAnalyzer(searchAnalyzer)
.Store(true)
.TermVector(TermVectorOption.no))));
And this is the search where the first character is missing:
SearchCriteria criteria = new SearchCriteria() { AccountName = "kitty" };
client.Search<SearchAccountResult>(s => s
.Index(index)
.Type(type)
.Query(q => q.Bool(b => b.Must(d => d.Match(m => m.OnField(r => r.AccountName).QueryString(criteria.AccountName)))))
.SortDescending("_score"))