我正在尝试编写一个使用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
排序,则没有错误。但这是一个非常有用的搜索。
有没有一种简单的方法可以解决这个问题?
答案 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 };
}
解决了这个问题。