我一直在尝试更新到ES6和NEST 6,并遇到NEST搜索请求序列化的问题-特别是序列化基本C#类型为枚举的Terms查询。
我已经在我的索引中将一个状态枚举映射为关键字,并通过使用NEST.JsonNetSerializer并按照Elasticsearch / NEST 6 - storing enums as string设置合同json转换器来正确地存储在其字符串表示形式中。
尝试基于此Status枚举进行搜索时出现问题。当我尝试使用术语查询指定多个值时,这些值在请求中被序列化为整数,并且由于类型不匹配而导致搜索找不到结果。
有趣的是,在Term查询中,该枚举已正确地序列化为字符串,因此,我认为在必须序列化枚举集合而不是单个枚举的情况下,将忽略StringEnumConverter。
让我们在代码中更清楚地显示它。这是用于定义索引的枚举和(简化的)模型:
public enum CampaignStatus
{
Active = 0,
Sold = 1,
Withdrawn = 2
}
public class SalesCampaignSearchModel
{
[Keyword]
public Guid Id { get; set; }
[Keyword(DocValues = true)]
public CampaignStatus CampaignStatus { get; set; }
}
下面是构建ElasticClient设置的摘要:
var pool = new SingleNodeConnectionPool(new Uri(nodeUri));
var connectionSettings = new ConnectionSettings(pool, (builtin, serializerSettings) =>
new JsonNetSerializer(builtin,
serializerSettings,
contractJsonConverters: new JsonConverter[]{new StringEnumConverter()}
)
)
.EnableHttpCompression();
以下是可正确返回结果的术语查询:
var singleTermFilterQuery = new SearchDescriptor<SalesCampaignSearchModel>()
.Query(x => x.Term(y => y.Field(z => z.CampaignStatus).Value(CampaignStatus.Active)));
生成请求:
{
"query": {
"term": {
"campaignStatus": {
"value": "Active"
}
}
}
}
以下是不返回结果的字词查询:
var termsFilterQuery = new SearchDescriptor<SalesCampaignSearchModel>()
.Query(x => x.Terms(y => y.Field(z => z.CampaignStatus).Terms(CampaignStatus.Active, CampaignStatus.Sold)));
生成请求:
{
"query": {
"terms": {
"campaignStatus": [
0,
1
]
}
}
}
到目前为止,我对JsonNetSerializer提出的选项有了很好的了解,尝试了一堆可用属性(NEST.StringEnumAttribute,[JsonConverter(typeof(StringEnumConverter))),而不是使用全局属性在客户端上,有一个显式的过滤器对象,在CampaignStatuses等的集合上设置了ItemConverterType等),而每一次需要对枚举进行查询的唯一成功的方法就是强力.ToString()。
这些是我尝试迁移到NEST 6的相当广泛的代码库中的玩具示例,因此我想要的是能够在某处指定全局配置,而不是多个开发人员团队需要注意这一点有点古怪。
是的...我已经看了几天了。我错过了一些愚蠢的好机会。否则,我想知道是否需要为某些JsonConverter提供一个与任意枚举集合匹配的协定,并且NEST及其经过调整的Json.NET序列化器是否应该已经在开箱即用地进行这种递归解析?
任何帮助将不胜感激,因为我对此感到有些发疯。