Elasticsearch动态字段映射:运行时将指定客户字段值填充到POCO属性
实现动态字段到POCO属性的映射
完全可以实现需求,并且通过自定义反序列化就能达成目标。以下是两种常见场景的具体实现方案:
一、直接处理JSON字符串(使用Newtonsoft.Json)
如果是从Elasticsearch获取到JSON字符串后再处理,可以通过自定义JsonConverter来动态匹配目标字段:
自定义转换器代码
public class PocoDynamicFieldConverter : JsonConverter<Poco> { private readonly string _customerName; public PocoDynamicFieldConverter(string customerName) { _customerName = customerName; } public override Poco ReadJson(JsonReader reader, Type objectType, Poco existingValue, bool hasExistingValue, JsonSerializer serializer) { var jObject = JObject.Load(reader); // 构造目标字段名 var targetField = $"field.{_customerName}"; // 取出对应字段值并赋值给POCO var fieldValue = jObject[targetField]?.ToString(); return new Poco { field = fieldValue }; } public override void WriteJson(JsonWriter writer, Poco value, JsonSerializer serializer) { // 若无需将POCO序列化为JSON,可抛出异常或留空 throw new NotImplementedException("序列化操作未实现"); } }
使用示例
// 运行时确定的客户名称 var targetCustomer = "customerA"; // 从Elasticsearch获取的JSON数据 var esJson = @"{ ""field.customerA"": 4, ""field.customerB"": 10 }"; // 反序列化时传入自定义转换器 var poco = JsonConvert.DeserializeObject<Poco>(esJson, new PocoDynamicFieldConverter(targetCustomer)); // 此时poco.field的值为"4"
二、结合Elasticsearch NEST客户端处理
如果使用官方NEST客户端查询数据,有两种更贴合场景的方式:
方式1:先过滤目标字段再构造POCO
通过SourceFilter只返回目标客户的字段,避免处理多余数据:
var targetCustomer = "customerB"; var client = new ElasticClient(new Uri("http://localhost:9200")); var searchResponse = client.Search<dynamic>(s => s .Index("your-index-name") .Query(q => q.MatchAll()) // 只包含目标客户的字段 .SourceFilter(f => f.Include($"field.{targetCustomer}")) ); // 遍历结果构造POCO foreach (var hit in searchResponse.Hits) { var fieldValue = hit.Source[$"field.{targetCustomer}"].ToString(); var poco = new Poco { field = fieldValue }; // 后续业务处理 }
方式2:给NEST配置自定义转换器
直接让NEST在反序列化时自动映射目标字段:
public class PocoNestConverter : JsonConverter<Poco> { private readonly string _customerName; public PocoNestConverter(string customerName) { _customerName = customerName; } public override Poco ReadJson(JsonReader reader, Type objectType, Poco existingValue, bool hasExistingValue, JsonSerializer serializer) { var jObject = JObject.Load(reader); var targetField = $"field.{_customerName}"; return new Poco { field = jObject[targetField]?.ToString() }; } public override void WriteJson(JsonWriter writer, Poco value, JsonSerializer serializer) { throw new NotImplementedException("序列化操作未实现"); } } // 配置NEST客户端 var settings = new ConnectionSettings(new Uri("http://localhost:9200")) .DefaultIndex("your-index-name") // 添加自定义转换器 .SerializerSettings(s => s.Converters.Add(new PocoNestConverter("customerA"))); var client = new ElasticClient(settings); // 查询时直接反序列化为Poco var response = client.Search<Poco>(s => s.Query(q => q.MatchAll())); // 返回的Poco对象已自动填充对应客户的字段值
内容的提问来源于stack exchange,提问作者Shirkan
相关产品推荐
相关产品推荐

