Elasticsearch自动完成问题

时间:2017-11-19 06:27:14

标签: nest elasticsearch-5

我正在尝试使用Elasticsearch.net创建自动完成功能,但我一直收到无效响应。

但是无法弄清楚为什么?

我的请求看起来像这样

var descriptor = new SearchDescriptor<EmployeeDocument>()
                .Index("employees").Type("employee").From(page - 1).Size(pageSize)
                .Suggest(
                s => s.Completion(
                    "my-completion-suggest",
                    c => c
                    .Field(f1 => f1.Description)
                    .Field(f1 => f1.empfirstname)
                    .Contexts(
                        queriesDescriptor => queriesDescriptor.Context(
                            "query-descriptor",
                            queryDescriptor => queryDescriptor.Prefix(true).Context(query)))));
            var response3 = await this.client.SearchAsync<EmployeeDocument>(descriptor);

我得到的错误是

Invalid NEST response built from a unsuccessful low level call on POST: /employees/employee/_search
 Audit trail of this API call:
 - [1] BadResponse: Node: http://192.168.2.29:9200/ Took: 00:00:00.3543244
 ServerError: ServerError: 400Type: search_phase_execution_exception Reason: "all shards failed"

这就是我调用方法的方法

var results1 = await service.SearchAsync("brenda", page, pageSize);
var results8 = await service.SearchAsync("something else", page, pageSize);

我的模型也很简单。我遗漏了一些属性

  [ElasticsearchType(Name = "employee")]
        public class EmployeeDocument
        {
            //[Text(Name = "pkempid")]
            public long pkempid { get; set; }

            //[Text(Name = "empfirstname")]
            public string empfirstname { get; set; }
        }

2 个答案:

答案 0 :(得分:2)

Descriptionempfirstname需要映射为completion field data types。 NEST中的CompletionField类型可用于属性类型,该类型将通过automapping映射为completion数据类型。

此外,完成建议者只能指定一个字段,因此将多个调用链接到.Field()将无法按预期工作(最后一次调用将是使用的字段)。但是,您可以在针对不同字段的一个请求中指定多个建议器。但是,更常见的是,不是在映射中具有多个完成字段,而是为单个完成字段指定多个输入值。

完成建议器的用例是在键入时提供快速搜索&#34;自动完成功能,权衡可以使用text字段数据类型执行的更复杂分析链的功能。

答案 1 :(得分:1)

好的,所以我想出了如何进行自动完成,我最终使用Edge NGram Tokenizer我需要做的第一件事就是使用正确的过滤器设置我的索引。

var response = this.client.CreateIndex(
                    ElasticConfig.IndexName,
                    index => index.Mappings(
                        ms => ms.Map<EmployeeDocument>(
                            m => m.Properties(
                                p => p
                                    .Text(t => t.Name(n => n.EmpFirstName).Analyzer("auto-complete").Fields(ff => ff.Keyword(k => k.Name("keyword"))))
                                    .Text(t => t.Name(n => n.pkEmpID).Analyzer("auto-complete-id").Fields(ff => ff.Keyword(k => k.Name("keyword"))))
                                    .Text(t => t.Name(n => n.Description).Analyzer("auto-complete").Fields(ff => ff.Keyword(k => k.Name("keyword")))))))
                        .Settings(f => f.Analysis(
                            analysis => analysis
                                .Analyzers(
                                    analyzers => analyzers
                                        .Custom("auto-complete", a => a.Tokenizer("standard").Filters("lowercase", "auto-complete-filter"))
                                        .Custom("auto-complete-id", a => a.Tokenizer("standard").Filters("lowercase", "auto-complete-id-filter")))
                                        .TokenFilters(tokenFilter => tokenFilter
                                                                    .EdgeNGram("auto-complete-filter", t => t.MinGram(3).MaxGram(5))
                                                                    .EdgeNGram("auto-complete-id-filter", t => t.MinGram(1).MaxGram(5))))));

然后进行实际搜索

var response = await this.client.SearchAsync<EmployeeDocument>(
                           x => x.Index("default-index").Type("employee").From(page - 1).Size(pageSize)
                                .Query(q => q
                                    .MultiMatch(m => m
                                        .Query(query)
                                        .Fields(f => f
                                                        .Field(_ => _.EmpFirstName)
                                                        .Field(_ => _.pkEmpID)
                                                        .Field(_ => _.Description))))
                                         .Highlight(
                                            h => h.PreTags("<mark>").PostTags("</mark>").Fields(
                                                f => f.Field(p => p.EmpFirstName),
                                                f => f.Field(p => p.pkEmpID),
                                                f => f.Field(p => p.Description))));