在Elasticsearch Nest中将一种类型映射到另一种类型

时间:2018-02-23 02:32:39

标签: elasticsearch uuid nest

我使用elasticsearch nest C#库来映射文档。一切顺利,除了自定义类型TypeX,我将其视为一个对象并存储为{}。

此自定义类型为v1 uuid,基本上被视为Guid。我真诚地希望将它作为Guid用于存储目的,因为它隐式地来回转换。因此弹性会将其视为Guid而不是TypeX。

根据attribute mapping部分,似乎我可以改变那种方式但是我并不想将Nest作为我的类型的依赖项公开,因为它在很多地方使用。

是否可以从连接或索引设置此映射以将TypeX映射到Guid和Guid到TypeX?

Nest:6.0.1

ES:6.2.2

2 个答案:

答案 0 :(得分:1)

System.Guid被映射为keyword数据类型,并使用NEST自动执行。鉴于以下文件

public class MyDocument
{
    public Guid UserId { get; set; }
}

以及以下映射

var client = new ElasticClient();

var createIndexResponse = client.CreateIndex("foo", c => c
    .Mappings(m => m
        .Map<MyDocument>(mm => mm
            .AutoMap()
        )
    )
);

将产生

{
  "mappings": {
    "mydocument": {
      "properties": {
        "userId": {
          "type": "keyword"
        }
      }
    }
  }
}

现在,要将您自己的类型映射为keyword类型,如果您不想将POCO归因,则可以使用流畅映射。给定以下POCO和自定义Uuid类型

public class Uuid
{
    private string _value;

    public Uuid(string value) => _value = value;

    public override string ToString() => _value;
}

public class MyDocument
{
    public Uuid UserId { get; set; }
}

这些可以用

映射
var createIndexResponse = client.CreateIndex("foo", c => c
    .Mappings(m => m
        .Map<MyDocument>(mm => mm
            .AutoMap()
            .Properties(p => p
                .Keyword(k => k
                    .Name(n => n.UserId)
                )
            )
        )
    )
);

生成与以前相同的映射。但是,这只是故事的一半,因为我们还需要控制Uuid的序列化和反序列化方式,以便将其序列化为JSON string并且实例可以由string构建。在NEST 6.x中,我们需要use our own serializer for this,因为NEST使用的序列化程序是内部的。

NEST.JsonSerializer nuget package包含一个使用Json.NET的自定义序列化程序,因此您可以编写JsonConverter来处理Uuid类型的序列化

public class UuidConverter : JsonConverter
{
    public override bool CanConvert(Type objectType) =>
        typeof(Uuid).IsAssignableFrom(objectType);

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) =>
        reader.TokenType == JsonToken.String
            ? new Uuid((string)reader.Value)
            : null;

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        if (value != null)
            writer.WriteValue(value.ToString());
        else
            writer.WriteNull();       
    }
}

private static void Main()
{
    var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));

    // configure NEST to use Json.NET for serialization of your documents
    // and register a custom converter to handle Uuid type
    var settings = new ConnectionSettings(pool, (builtin, s) => 
        new JsonNetSerializer(builtin, s, contractJsonConverters:
            new [] { new UuidConverter() }
        ))
        .DefaultIndex("foo");

    var client = new ElasticClient(settings);

    var createIndexResponse = client.CreateIndex("foo", c => c
        .Mappings(m => m
            .Map<MyDocument>(mm => mm
                .AutoMap()
                .Properties(p => p
                    .Keyword(k => k
                        .Name(n => n.UserId)
                    )
                )
            )
        )
    );

    var document = new MyDocument
    {
        UserId = new Uuid("123e4567-e89b-12d3-a456-426655440000")  
    };

    var indexResponse = client.IndexDocument(document);
}

文档索引请求然后将Uuid序列化为字符串

POST http://localhost:9200/foo/mydocument
{
  "userId": "123e4567-e89b-12d3-a456-426655440000"
}

答案 1 :(得分:0)

您可以使用流畅映射而不是属性映射(属性映射链接中的下一页)