Elasticsearch对映射放置方法的错误请求

时间:2018-07-27 13:16:44

标签: elasticsearch asp.net-core nest

我试图在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

1 个答案:

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

注意:您需要删除索引并重新创建,才能更改映射。使用别名与索引进行交互是一个好主意,以便您可以在开发时迭代映射