Elasticsearch.Nest 教程系列 9-3 转换:Ids inference | Id 文档标识推断


不少 Elasticsearch API 都需要传递一个 Id 类型的对象。这是一种特殊类型,以下几种类型会自动隐式转换为 Id 类型:

  • Int32
  • Int64
  • String
  • Guid

方法签名中,入参如果需要一个 Id 类型,那么传入以上 4 种类型的时候会自动隐式转换为 Id 类型。

Id idFromInt = 1;
Id idFromLong = 2L;
Id idFromString = "hello-world";
Id idFromGuid = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E");

从类型中推断 Id

Nest 并无法直接从一个类型对象中推断出 Id,但提供了 Id.From 方法:

假设你有如下类:

class MyDTO
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string OtherName { get; set; }
}
  • 默认情况下 Nest 会尝试在类上通过反射查找被命名为 Id 的属性,并基于该属性的 Getter 访问器创建一个被缓存的委托,如下,会将 MyDTO.Id 属性推断为 ES 中的 Id 类型:

var dto = new MyDTO
{
    Id = new Guid("D70BD3CF-4E38-46F3-91CA-FCBEF29B148E"),
    Name = "x",
    OtherName = "y"
};

你也可以在 ConnectionSettings 上指定一个不会自动推断的属性作为 Id,如下:

var settings = new ConnectionSettings(new Uri(_esSettings.ServerUri))
        .DefaultMappingFor<MyDTO>(m => m.IdProperty(ip=>ip.Name))

//你也可以使用非泛型的方法:
var settings = new ConnectionSettings(new Uri(_esSettings.ServerUri))
        .DefaultMappingFor<MyDTO>(m => m.IdProperty(typeof(MyDTO).GetProperty(nameof(MyDTO.Name)).Name))
  • 将 MyDTO.Name 属性作为 ES 中的 Id。

P.S.:每个 ConnectionSettings 实例都会缓存推理规则。

  • 因为是基于每个 ConnectionSettings 实例进行缓存的,所以你可以使用不同的推断规则来创建另一个 ConnectionSettings 实例:

使用 ElasticsearchType 特性进行推断

另外要给推断 Id 的方法是在类上标记 ElasticsearchType 特性。

eg:将 Name 属性作为 ES 的 Id:

[ElasticsearchType(IdProperty = nameof(Name))]
class MyOtherDTO
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string OtherName { get; set; }
}
  • 这样子标记后,就不需要再在 ConnectionSettigns 上进行指定了。

禁用 Id 推断

你可以关闭 CLR 类型自动推断 Id

//eg:关闭 MyDTO 类的 Id 自动推断
var settings = new ConnectionSettings(new Uri(_esSettings.ServerUri))
        .DefaultMappingFor<MyDTO>(m => m.DisableIdInference())

// eg:直接在 ConnectionSettings 上进行全局关闭
var settings = new ConnectionSettings(new Uri(_esSettings.ServerUri))
        .DefaultDisableIdInference(true)

//eg:全局关闭,但在 MyDTO 上开启
var settings = new ConnectionSettings(new Uri(_esSettings.ServerUri))
        .DefaultDisableIdInference(true)
        .DefaultMappingFor<MyDTO>(m => m.DisableIdInference(false))