Elasticsearch(C# nest):地图摘要属性

Elasticsearch(C# nest): Map abstract property

我在 C# 中有一个 class ProductDiscount。其他 class 继承自它(FlatDiscount、PercentageDiscount 等)。

在 Elastic 中存储数据似乎可行,但我无法从 Elastic 读取数据。

我收到此错误: 无法创建 ProductDiscount 类型的实例。类型是一个接口或抽象 class 并且不能被实例化。路径 'discount.amount',第 1 行,位置 1098。

当我查看我的索引时,折扣确实是集合中的 storef,但没有指示 class 的类型。

是否可以使用 nest 客户端在 c# 中映射抽象 属性?

我试过这个映射描述符但没有成功:

mappingsDescriptor.Map<Product>(x => x
                .Properties(props => props

                    .Object<ProductDiscount>(o => o.Name(prop => prop.Discount))
                    .Object<FlatProductDiscount>(o => o.Name(prop => prop.Discount).AutoMap())
                    .Object<PercentageProductDiscount>(o => o.Name(prop => prop.Discount).AutoMap())
                    .Object<FreeProductProductDiscount>(o => o.Name(prop => prop.Discount).AutoMap())
                    .Object<QuantityProductDiscount>(o => o.Name(prop => prop.Discount).AutoMap())
                 )
            );

使用 ElasticClient 完成读取:

    var result = await ElasticClient.SearchAsync<Product>(new SearchRequest(Indices.Index(index: CollectionName)));

我找到了解决办法!!

我使用 JsonSubTypes package 写了一个自定义转换器。

    private static JsonConverter DiscountConverter()
    {
        var assembly = Assembly.GetAssembly(typeof(ProductDiscount));

        var builder = JsonSubtypesConverterBuilder
            .Of(typeof(ProductDiscount), "Type");

        assembly
            .GetTypes()
            .Where(type => type.IsSubclassOf(typeof(ProductDiscount)) && !type.IsAbstract)
            .ForEach(s =>
            {
                builder.RegisterSubtype(s, s.Name);
            });

        var converter = builder
            .SerializeDiscriminatorProperty()
            .Build();

        return converter;
    } 

我的连接是这样设置的

            var pool = new SingleNodeConnectionPool(new Uri(uris.First()));
            connectionSettings = new ConnectionSettings(pool, connection, SourceSerializer());

    private static ConnectionSettings.SourceSerializerFactory SourceSerializer()
    {
        return (builtin, settings) => new JsonNetSerializer(builtin, settings,
            () => new JsonSerializerSettings
            {
                Converters = new List<JsonConverter>
                {
                    new StringEnumConverter(),
                    DiscountConverter()
                }
            });
    }