Nest SuggestCompletion 用法,抛出“不是完成建议字段”异常

问题描述 投票:0回答:1

我是elasticsearch的初学者,我一直在尝试使用elasticsearch的完成建议器,使用Nest在属性上自动完成。

这是我的映射(如此处所述:):

var createResult = client.CreateIndex(indexName, index => index                
            .AddMapping<Contact>(tmd => tmd
                .Properties(props => props
                    .Completion(s =>
                        s.Name(p => p.CompanyName.Suffix("completion"))
                        .IndexAnalyzer("standard")
                        .SearchAnalyzer("standard")
                        .MaxInputLength(20)
                        .Payloads()
                        .PreservePositionIncrements()
                        .PreserveSeparators())                        
                )
            )
        );

var resultPerson = client.IndexMany(documents.OfType<Person>(), new SimpleBulkParameters { Refresh = true });
var resultCompany = client.IndexMany(documents.OfType<Company>(), new SimpleBulkParameters { Refresh = true });

在索引时,我只是利用

IndexMany
方法并传递
IEnumerable<Contact>
(Contact 有一个名为 CompanyName 的属性,Contact 是一个抽象类,Person 和 Company 都是它的具体实现)。搜索抛出异常

ElasticSearchException[字段 [companyName] 不是完成建议字段]

查询如下所示:

SearchDescriptor<Contact> descriptor = new SearchDescriptor<Contact>();
descriptor = descriptor.SuggestCompletion("suggest", c => c.OnField(f => f.CompanyName).Text(q));

var result = getElasticClientInstance("contacts").Search<Contact>(body => descriptor);

string qe = result.ConnectionStatus.ToString();

我在这里做错了什么,我在

SuggestCompletion
上查看了 Nest 的测试,但没有太多帮助,这意味着测试仅描述如何获取建议,而不描述如何为 SuggestCompletion 设置索引映射。

我还尝试设置

edgeNgram
标记器,如本post中所述,但是也无法继续。

有关如何进行的任何指示或示例都会有很大帮助。

c# elasticsearch nest
1个回答
5
投票

更新

您尝试创建一个名为“companyName.completion”的属性,但在该位置它无效,它将使用最后一个标记“completion”。所以它实际上映射了一个名为completion的字段......尝试将调用更改为:

.Name(p => p.CompanyName)

其他观察

您为

Contact
指定映射,但在索引时使用
Person
Company
类型。

用你映射的elasticsearch术语来说:

/index/contact/

但是您的文件将进入:

/index/person/
/index/company

NEST 不会自动映射特定类的所有实现,elasticsearch 无法知道这三个类是相关的。

我将重构到方法的映射,并为涉及的所有类型调用它。

 var createResult = client.CreateIndex(indexName, index => index                
      .AddMapping<Contact>(tmd => MapContactCompletionFields(tmd))
      .AddMapping<Person>(tmd => MapContactCompletionFields(tmd))
      .AddMapping<Company>(tmd => MapContactCompletionFields(tmd))   
  );

 private RootObjectMappingDescriptor<TContact>  MapContactCompletionFields<TContact>(
      RootObjectMappingDescriptor<TContact> tmd)
      where TContact : Contact
 {
      return  tmd.Properties(props => props
           .Completion(s => s
                .Name(p => p.CompanyName.Suffix("completion"))
                .IndexAnalyzer("standard")
                .SearchAnalyzer("standard")
                .MaxInputLength(20)
                .Payloads()
                .PreservePositionIncrements()
                .PreserveSeparators()
           )                        
       );
 } 

该方法返回描述符,以便您可以进一步链接它。

然后当您搜索联系人时:

var result = getElasticClientInstance("contacts").Search<Contact>(
    body => descriptor
        .Types(typeof(Person), typeof(Company))
);

该类型提示将导致搜索查找

/index/person
/index/company
并将知道如何返回文档的协变列表。

因此您可以在上次通话后执行

result.Documents.OfType<Person>()

© www.soinside.com 2019 - 2024. All rights reserved.