NEST按文本字段排序

时间:2017-10-27 16:33:33

标签: c# elasticsearch nest

我正在尝试编写一个使用NEST的搜索模块,并将搜索功能保留在自己的有限上下文中。

为实现这一目标,我进行了以下用户个人资料搜索:

public class UserProfileSearch : IUserProfileSearch
{
    ...

    public async Task<PagedItems<UserProfileModel>> FindAsync(string searchTerm, int skip, int take)
    {
        var client = _elasticClientProvider.GetClient();
        var response = await client.SearchAsync<ElasticUserProfileModel>(s => s
            .Index(_elasticConfiguration.GetIndex())
            .From(skip).Size(take)
            .Query(q => q.MultiMatch(m => m.Fields(f => f
                .Field(u => u.Email)
                .Field(u => u.FirstName)
                .Field(u => u.LastName))
                .Query(searchTerm)))
            .Sort(q => q.Ascending(u => u.Email)));
        var count = await client.CountAsync<ElasticUserProfileModel>(s => s.Index(_elasticConfiguration.GetIndex()));
        return new PagedItems<UserProfileModel> { Items = response.Documents.Cast<UserProfileModel>().ToArray(), Total = count.Count };
    }
}

此报告的响应失败:

  

{&#34;错误&#34; {&#34; ROOT_CAUSE&#34;:[{&#34;类型&#34;:&#34; illegal_argument_exception&#34;&#34;理由&#34 ;:&#34; Fielddata   默认情况下在文本字段上禁用。在[email]上设置fielddata = true   为了通过反转倒置来加载内​​存中的fielddata   指数。请注意,这可能会占用大量内存。   或者使用关键字字段   。代替&#34;}],&#34;类型&#34;:&#34; search_phase_execution_exception&#34;&#34;理由&#34;:&#34;所有   碎片   失败&#34;&#34;相&#34;:&#34;查询&#34;&#34;分组&#34;:真,&#34; failed_shards&#34;:[{&#34;碎片& #34;:0,&#34;指数&#34;:&#34; XXXX&#34;&#34;节点&#34;:&#34; XXXX&#34;&#34;理由&#34; :{&#34;类型&#34;:&#34; illegal_argument_exception&#34;&#34;理由&#34;:&#34; Fielddata   默认情况下在文本字段上禁用。在[email]上设置fielddata = true   为了通过反转倒置来加载内​​存中的fielddata   指数。请注意,这可能会占用大量内存。   或者,也可以使用关键字字段。&#34;}}]},&#34; status&#34;:400}

但是,我已经完成了报告中的建议,但同样的错误仍在继续。我已经定义了

public class ElasticUserProfileModel : UserProfileModel
{
    [Text(Fielddata = true)] public override string Email { get => base.Email; set => base.Email = value; }
}

这应该是报告所要求的。我在每次端到端测试期间使用ElasticUserProfileModel重建索引。

我还尝试使用Keyword属性而不是Text属性,但这会产生完全相同的错误。

如果按Id(数字)而不是Email排序,则没有错误。但这是一个非常有用的搜索。

有没有一种简单的方法可以解决这个问题?

1 个答案:

答案 0 :(得分:1)

根据https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/multi-fields.html的文档,我发现POCO字符串会自动映射到关键字和文本字段。我只需要Suffix()扩展方法即可启用字符串排序。

我删除了ElasticUserProfileModel派生类,FindAsync()方法变为

public async Task<PagedItems<UserProfileModel>> FindAsync(string searchTerm, int skip, int take)
{
    var client = _elasticClientProvider.GetClient();
    var response = await client.SearchAsync<UserProfileModel>(s => s
        .Index(_elasticConfiguration.GetIndex())
        .From(skip).Size(take)
        .Query(q => q.MultiMatch(m => m.Fields(f => f
            .Field(u => u.Email)
            .Field(u => u.FirstName)
            .Field(u => u.LastName))
            .Query(searchTerm)))
        .Sort(q => q.Ascending(u => u.Email.Suffix("keyword"))));
    var count = await client.CountAsync<UserProfileModel>(s => s.Index(_elasticConfiguration.GetIndex()));
    return new PagedItems<UserProfileModel> { Items = response.Documents.ToArray(), Total = count.Count };
}

解决了这个问题。