Elasticsearch 对映射 put 方法的错误请求

Elasticsearch bad request on mapping put method

我正在尝试在 Elastic Search 中创建一个索引,并添加分析器和 maaping 来处理 @ 等特殊字符,以便在电子邮件字段中进行搜索。这是我的代码

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;
    }

设置分析器

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 方法上出现错误

The remote server returned an error: (400) Bad Request.

Elastic 版本为 1.7.5

Nest 版本为 5.5

问题是

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"
}

注意:您需要删除索引并重新创建,以更改映射。使用别名与索引交互是个好主意,这样您就可以在开发过程中迭代映射。