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

  • 本系列博文是“伪”官方文档翻译(更加本土化),并非完全将官方文档进行翻译,而是在查阅、测试原始文档并转换为自己真知灼见后的“准”翻译。有不同见解 / 说明不周的地方,还请海涵、不吝拍砖 :)

  • 官方文档见此:https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/introduction.html

  • 本系列对应的版本环境:ElasticSearch@7.3.1,NEST@7.3.1,IDE 和开发平台默认为 VS2019,.NET CORE 2.1


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

  • Int32

  • Int64

  • String

  • Guid

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

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

从类型中推断 Id

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

假设你有如下类:

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

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

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

1
2
3
4
5
6
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))

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

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

使用 ElasticsearchType 特性进行推断

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

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

1
2
3
4
5
6
7
[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

1
2
3
4
5
6
7
8
9
10
11
12
//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))