C# Elasticsearch嵌套:不带通配符的部分/全文搜索
我想为我的用户提供一个搜索引擎。假设用户类是:C# Elasticsearch嵌套:不带通配符的部分/全文搜索,c#,.net,elasticsearch,nest,C#,.net,elasticsearch,Nest,我想为我的用户提供一个搜索引擎。假设用户类是: public class User { public string Code { get; set; } public string Name { get; set; } } 我的数据库中有这样的用户: (1) new User { Code = "XW1234", Name = "John Doe" }, (2) new User { Code = "AD4567", Name = "Jane Doe" } 因此: 当我的查
public class User
{
public string Code { get; set; }
public string Name { get; set; }
}
我的数据库中有这样的用户:
(1) new User { Code = "XW1234", Name = "John Doe" },
(2) new User { Code = "AD4567", Name = "Jane Doe" }
因此:
当我的查询是:“doe”(注意小写)时,我希望看到(1)和(2)
当我的问题是:“4”时,我希望看到(1)和(2)
当我的查询是:“x”时,我想看到(1)
当我的问题是:“ja”时,我想看到(2)
我希望与SQL中的%doe%类似。请不要介意长度-我将使用至少3个字母。这只是一个例子
我有一个使用通配符的解决方案——虽然有效,但性能很差
我试图将索引配置为使用ngram标记器,但没有成功-我收到了一个空集合
我还检查了这个(“从开始”方法):
没有成功
请提供C#代码。我不知道我是否正确地翻译了弹性搜索JSON
编辑
根据第一条评论,我试着这样做:
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;
}
private const string DefaultIndexName=“test”;
私有常量字符串ElasticSearchServerUri=@”http://192.168.99.100:32769";
私有静态只读IndexName UsersIndexName=“users”;
公共IElasticClient CreateElasticClient()
{
var settings=CreateConnectionSettings();
var客户端=新的ElasticClient(设置);
var studentsIndexDescriptor=new CreateIndexDescriptor(UsersIndexName)
.Mappings(ms=>ms
.Map(m=>m
.Properties(ps=>ps
.String(s=>s
.Name(n=>n.Code)
.Analyzer(“子字符串_分析器”);
CreateIndex(UsersIndexName,descriptor=>studentsIndexDescriptor
.Settings(s=>s
.分析(a=>a
.分析仪(分析仪=>analyzer
.Custom(“子字符串\分析器”,analyzerDescriptor=>analyzerDescriptor.Tokenizer(“标准”)。过滤器(“小写”、“子字符串”))
.TokenFilters(tf=>tf
.NGram(“substring”,filterDescriptor=>filterDescriptor.MinGram(2).MaxGram(15‘‘‘‘‘)’);
返回客户;
}
私有静态连接设置CreateConnectionSettings()
{
var uri=新uri(ElasticSearchServerUri);
var设置=新连接设置(uri);
设置
.DefaultIndex(DefaultIndexName);
返回设置;
}
我使用了这个查询:
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;
}
公共IEnumerable搜索(字符串查询)
{
var result=elasticClient.Search(描述符=>descriptor
.Query(q=>q
.QueryString(queryDescriptor=>queryDescriptor.Query(Query).Fields(fs=>fs.Fields(f1=>f1.Codeщ));
返回结果。文件;
}
没用
我试过密码:“1234”和“5678”。我试图用“23”、“5”进行查询,但没有结果。
当我搜索“1234”时,它会返回正确的用户。我怀疑在您的代码中:
用户
索引,因此将用户编入默认索引用户
索引,因此将根据默认索引test
进行查询。此索引包含索引文档,但是code
字段不使用substring\u分析器分析,因为此分析是在users
索引中定义的
连接设置
,.InferMappingFor()
上提供了一个配置选项,以将particualr POCO类型与特定的索引名相关联;如果未在请求中指定索引,并且优先于默认索引,则将使用此索引
var uri = new Uri(ElasticSearchServerUri);
var settings = new ConnectionSettings(uri)
.DefaultIndex(DefaultIndexName)
.InferMappingFor<User>(d => d
.IndexName(UsersIndexName)
);
var uri=新uri(ElasticSearchServerUri);
var设置=新连接设置(uri)
.DefaultIndex(DefaultIndexName)
.InferMappingFor(d=>d
.IndexName(UsersIndexName)
);
代码的其余部分是正确的。下面是一个完整的工作示例
private const string DefaultIndexName = "test";
private const string ElasticSearchServerUri = @"http://localhost:9200";
private const string UsersIndexName = "users";
void Main()
{
var client = CreateElasticClient();
var users = new[] {
new User { Code = "XW1234", Name = "John Doe" },
new User { Code = "AD4567", Name = "Jane Doe" }
};
client.IndexMany(users);
// refresh the index after indexing so that the documents are immediately
// available for search. This is good for testing,
// but avoid doing it in production.
client.Refresh(UsersIndexName);
var result = client.Search<User>(descriptor => descriptor
.Query(q => q
.QueryString(queryDescriptor => queryDescriptor
.Query("1234")
.Fields(fs => fs
.Fields(f1 => f1.Code)
)
)
)
);
// outputs 1
Console.WriteLine(result.Total);
}
public class User
{
public string Code { get; set; }
public string Name { get; set; }
}
public IElasticClient CreateElasticClient()
{
var settings = CreateConnectionSettings();
var client = new ElasticClient(settings);
// this is here so that the example can be re-run.
// Remove this!
if (client.IndexExists(UsersIndexName).Exists)
{
client.DeleteIndex(UsersIndexName);
}
client.CreateIndex(UsersIndexName, descriptor => descriptor
.Mappings(ms => ms
.Map<User>(m => m
.AutoMap()
.Properties(ps => ps
.String(s => s
.Name(n => n.Code)
.Analyzer("substring_analyzer")
)
)
)
)
.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)
.DefaultIndex(DefaultIndexName)
.InferMappingFor<User>(d => d
.IndexName(UsersIndexName)
);
return settings;
}
private const string DefaultIndexName=“test”;
私有常量字符串ElasticSearchServerUri=@”http://localhost:9200";
private const string UsersIndexName=“users”;
void Main()
{
var client=CreateElasticClient();
var users=new[]{
新用户{Code=“XW1234”,Name=“John Doe”},
新用户{Code=“AD4567”,Name=“Jane Doe”}
};
client.IndexMany(用户);
//编制索引后刷新索引,以便立即删除文档
//可供搜索。这对测试很好,
//但避免在生产中这样做。
client.Refresh(UsersIndexName);
var result=client.Search(描述符=>descriptor
.Query(q=>q
.QueryString(queryDescriptor=>queryDescriptor
.Query(“1234”)
.Fields(fs=>fs
.Fields(f1=>f1.Code)
)
)
)
);
//产出1
Console.WriteLine(result.Total);
}
公共类用户
{
公共字符串代码{get;set;}
公共字符串名称{get;set;}
}
公共IElasticClient CreateElasticClient()
{
var settings=CreateConnectionSettings();
var客户端=新的ElasticClient(设置);
//这是为了使示例可以重新运行。
//把这个拿走!
if(client.indexists(UsersIndexName.Exists)
{
client.DeleteIndex(UsersIndexName);
}
CreateIndex(UsersIndexName,descriptor=>descriptor
.Mappings(ms=>ms
.Map(m=>m
.AutoMap()
.Properties(ps=>ps
.String(s=>s
.Name(n=>n.Code)
.Analyzer(“子字符串\分析器”)
)
)
)
)
.Settings(s=>s
.分析(a=>a
.分析仪(分析仪=>analyzer
.Custom(“子字符串\分析器”,analyzerDescriptor=>analyzerDescriptor
.Tokenizer(“标准”)
.Filters(“小写”、“子字符串”)
)
)