在 Elasticsearch Nest 中将一种类型映射到另一种类型
In Elasticsearch Nest mapping one type to another
我正在使用 elasticsearch nest C# 库来映射文档。除了我拥有的自定义类型 TypeX 之外,一切都很顺利,它被视为对象并存储为 { }。
此自定义类型是 v1 uuid,本质上被视为 Guid。老实说,我想将它转换为 Guid 用于存储目的,因为它隐式地来回转换。因此 elastic 会将其视为 Guid 而不是 TypeX。
根据 attribute mapping 部分,我似乎可以通过这种方式更改类型,但是我真的不想将 Nest 公开为我的类型的依赖项,因为它在许多地方使用。
是否可以从连接或索引设置此映射以将 TypeX 映射到 Guid 并将 Guid 映射到 TypeX?
嵌套:6.0.1
ES: 6.2.2
您可以使用流畅映射而不是属性映射(属性映射的下一页 link)
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
的序列化和反序列化方式,使其序列化为JSONstring
并且可以从 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"
}
我正在使用 elasticsearch nest C# 库来映射文档。除了我拥有的自定义类型 TypeX 之外,一切都很顺利,它被视为对象并存储为 { }。
此自定义类型是 v1 uuid,本质上被视为 Guid。老实说,我想将它转换为 Guid 用于存储目的,因为它隐式地来回转换。因此 elastic 会将其视为 Guid 而不是 TypeX。
根据 attribute mapping 部分,我似乎可以通过这种方式更改类型,但是我真的不想将 Nest 公开为我的类型的依赖项,因为它在许多地方使用。
是否可以从连接或索引设置此映射以将 TypeX 映射到 Guid 并将 Guid 映射到 TypeX?
嵌套:6.0.1
ES: 6.2.2
您可以使用流畅映射而不是属性映射(属性映射的下一页 link)
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
的序列化和反序列化方式,使其序列化为JSONstring
并且可以从 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"
}