I want to have a search engine for my users. Let's say user class is:
public class User
{
public string Code { get; set; }
public string Name { get; set; }
}
I have such users in my db:
(1) new User { Code = "XW1234", Name = "John Doe" },
(2) new User { Code = "AD4567", Name = "Jane Doe" }
So:
When my query is: "doe" (mind the lowercase) I want to see (1) and (2)
When my query is: "4" I want to see (1) and (2)
When my query is: "x" I want to see (1)
When my query is: "ja" I want to see (2)
I want to work similarly as like %doe%
in SQL. Please don't mind queries length - I will use 3 letters minimum. This is just an example.
I have a solution with wildcards - works but performance is poor.
I was trying to configure index to use ngram tokenizer but no success - I was receiving an empty collection.
I also checked this ("starts with" approach): https://www.elastic.co/guide/en/elasticsearch/guide/current/_index_time_search_as_you_type.html No success.
Please provide the C# code. I don't know if I'm translating the Elastic search jsons correctly.
EDIT According to the first comment I tried this:
private const string DefaultIndexName = "test";
private const string ElasticSearchServerUri = @"http://192.168.99.100:32769";
private static readonly IndexName UsersIndexName = "users";
public IElasticClient CreateElasticClient()
{
var settings = CreateConnectionSettings();
var client = new ElasticClient(settings);
var studentsIndexDescriptor = new CreateIndexDescriptor(UsersIndexName)
.Mappings(ms => ms
.Map<User>(m => m
.Properties(ps => ps
.String(s => s
.Name(n => n.Code)
.Analyzer("substring_analyzer")))));
client.CreateIndex(UsersIndexName, descriptor => studentsIndexDescriptor
.Settings(s => s
.Analysis(a => a
.Analyzers(analyzer => analyzer
.Custom("substring_analyzer", analyzerDescriptor => analyzerDescriptor.Tokenizer("standard").Filters("lowercase", "substring")))
.TokenFilters(tf => tf
.NGram("substring", filterDescriptor => filterDescriptor.MinGram(2).MaxGram(15))))));
return client;
}
private static ConnectionSettings CreateConnectionSettings()
{
var uri = new Uri(ElasticSearchServerUri);
var settings = new ConnectionSettings(uri);
settings
.DefaultIndex(DefaultIndexName);
return settings;
}
And I used this query:
public IEnumerable<User> Search(string query)
{
var result = elasticClient.Search<User>(descriptor => descriptor
.Query(q => q
.QueryString(queryDescriptor => queryDescriptor.Query(query).Fields(fs => fs.Fields(f1 => f1.Code)))));
return result.Documents;
}
Didn't work.
I tried Codes: "1234" and "5678". I tried to query with "23", "5" - no results. When I search for "1234" - it returns the correct user.