我试图在Elastic Search中创建索引,并添加分析器和映射以处理诸如@之类的特殊字符以在Email字段中进行搜索。这是我的代码
Analyzer.txt
{
"analysis": {
"analyzer": {
"email_search": {
"type": "custom",
"tokenizer": "uax_url_email",
"filter": [ "lowercase", "stop" ]
}
}
}
Mapping.txt
{"users":
{
"properties": {
"email": {
"type": "string",
"analyzer": "email_search"
}
}
}
CreatedIndex
string _docuementType ="users";
string _indexName="usermanager";
public bool Index(T entity)
{
SetupAnalyzers();
SetupMappings();
var indexResponse = _elasticClient.Index(entity, i => i.Index(_indexName)
.Type(_docuementType)
.Id(entity.Id));
return indexResponse.IsValid;
}
SetupAnalyzer
protected void SetupAnalyzers()
{
if (!_elasticClient.IndexExists(_indexName).Exists)
{
_elasticClient.CreateIndex(_indexName);
}
using (var client = new System.Net.WebClient())
{
string analyzers = File.ReadAllText("analyzers.txt");
client.UploadData("http://localhost:9200/usermanager/_settings", "PUT", Encoding.ASCII.GetBytes(analyzers));
}
}
SetupMappings
protected void SetupMappings()
{
using (var client = new System.Net.WebClient())
{
var mappings = File.ReadAllText("mappings.txt");
client.UploadData("http://localhost:9200/usermanager/users/_mapping", "PUT", Encoding.ASCII.GetBytes(mappings));
}
}
但是在 SetupMappings 方法上出现错误
远程服务器返回错误:(400)错误的请求。
弹性版本为1.7.5
嵌套版本为5.5
答案 0 :(得分:1)
问题是
var indexResponse = _elasticClient.Index(entity, i => i.Index(_indexName)
.Type(_docuementType)
.Id(entity.Id));
您正在索引文档之前设置映射和分析器;在这种情况下,Elasticsearch将自动创建索引,从它看到的第一个文档推断一个映射,并且将使用标准分析器将字符串属性映射为analyzed string fields。
要解决此问题,应在为所有文档建立索引之前,先创建索引,分析器和映射。您也可以disable auto index creation if you need to, in elasticsearch.yml config。这是否是一个好主意取决于您的用例。具有已知索引和显式映射的搜索用例就是您可能考虑禁用它的情况。
因此,程序流程将类似于
void Main()
{
var indexName = "usermanager";
var typeName = "users";
var settings = new ConnectionSettings(new Uri("http://localhost:9200"))
.MapDefaultTypeNames(d => d
// map the default index to use for the User type
.Add(typeof(User), typeName)
)
.MapDefaultTypeIndices(d => d
// map the default type to use for the User type
.Add(typeof(User), indexName)
);
var client = new ElasticClient(settings);
if (!client.IndexExists(indexName).Exists)
{
client.CreateIndex(indexName, c => c
.Analysis(a => a
.Analyzers(aa => aa
.Add("email_search", new CustomAnalyzer
{
Tokenizer = "uax_url_email",
Filter = new [] { "lowercase", "stop" }
})
)
)
.AddMapping<User>(m => m
.Properties(p => p
.String(s => s
.Name(n => n.Email)
.Analyzer("email_search")
)
)
)
);
}
client.Index(new User { Email = "me@example.com" });
}
public class User
{
public string Email { get; set; }
}
它将发送以下请求(假设索引不存在)
HEAD http://localhost:9200/usermanager
POST http://localhost:9200/usermanager
{
"settings": {
"index": {
"analysis": {
"analyzer": {
"email_search": {
"tokenizer": "uax_url_email",
"filter": [
"lowercase",
"stop"
],
"type": "custom"
}
}
}
}
},
"mappings": {
"users": {
"properties": {
"email": {
"analyzer": "email_search",
"type": "string"
}
}
}
}
}
POST http://localhost:9200/usermanager/users
{
"email": "me@example.com"
}
注意:您需要删除索引并重新创建,才能更改映射。使用别名与索引进行交互是一个好主意,以便您可以在开发时迭代映射