如何在没有属性映射的Elasticsearch 5.6中将枚举保存为字符串(使用NEST)

时间:2017-09-19 12:35:28

标签: c# elasticsearch nest

我想在Elasticsearch索引中以字符串的形式存储我的所有枚举。由于我使用的模型需要独立于任何特定技术,因此我无法使用attribute mappings

我知道您可以在创建SerializerFactory时传递ConnectionSettings,但我不知道哪个选项会更改枚举的序列化。

以下是我用来连接NEST的代码:

var serializers = new SerializerFactory(<what to put here?>);
var settings = new ConnectionSettings(myUri, serializers)
    .DefaultIndex(myIndex)
    .InferMappingFor<MyModel>(m => m
        .IdProperty(s => s.MyId)
    );
var client = new ElasticClient(settings);

我可以使用SerializerFactory将所有枚举保存为字符串吗?没有使用属性映射还有其他选项吗?

Elasticsearch版本:

"version" : {
    "number" : "5.6.0",
    "build_hash" : "781a835",
    "build_date" : "2017-09-07T03:09:58.087Z",
    "build_snapshot" : false,
    "lucene_version" : "6.6.0"
}

NEST版本:5.5.0(最新的nuget)

2 个答案:

答案 0 :(得分:2)

感谢@RussCam,我可以找到解决方案。这是我现在使用的代码:

var connectionPool = new SingleNodeConnectionPool(new Uri(myUri));
var connection = new HttpConnection();
var serializers = new SerializerFactory((s, v) => s.Converters.Add(new StringEnumConverter()) );

var settings = new ConnectionSettings(connectionPool, connection, serializers)
    .DefaultIndex(StatusIndex)
    .InferMappingFor<MyModel>(m => m
        .IdProperty(s => s.MyId)
    );

var client = new ElasticClient(settings);

第3行是重要的一行。添加到StringEnumConverter的{​​{1}}的{​​{1}}会将每个枚举序列化为字符串并从字符串反序列化(使用此Converters)。

答案 1 :(得分:0)

我使用了与@Leifb建议的类似方法(在属性上使用StringEnumConverter):

[JsonConverter(typeof(StringEnumConverter))] 
public MyEnum Status {get;set;}

但是,如果对类型使用自动映射,则会产生问题,因此我为此创建了一个通用的Enum to String属性访问者:

var result = await _client.PutIndexTemplateAsync(
    p.TemplateName, s=>s
        .Template(p.Template)
        .Mappings(m=>m
            .Map(p.TemplateName, mm=>mm
                .AutoMap<MyType>(new EnumAsStringPropertyVisitor())
            )
        ));


public class EnumAsStringPropertyVisitor : NoopPropertyVisitor
{
    public override void Visit(
        INumberProperty type,
        PropertyInfo propertyInfo,
        ElasticsearchPropertyAttributeBase attribute) 
    {
        if(propertyInfo.PropertyType.IsEnum)
        { 
            type.Type = "keyword"; 
        }
    }
}