Elasticsearch.Nest 教程系列 4-1 映射:Auto mapping | 自动映射
本系列博文是“伪”官方文档翻译(更加本土化),并非完全将官方文档进行翻译,而是在查阅、测试原始文档并转换为自己真知灼见后的“准”翻译。有不同见解 / 说明不周的地方,还请海涵、不吝拍砖 :)
官方文档见此: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
类似于 dynamic mapping,在创建索引或通过 Put Mapping API 创建映射时,NEST 提供了一种称为自动映射的功能,该功能可以从正在映射的 CLR POCO 属性类型自动推断出正确的 Elasticsearch 字段数据类型。
一个简单示例:
-
新建 Document 抽象基类。
-
新建 Company 类
-
新建 Employee 类
-
三者关系如下
1 | public abstract class Document |
自动映射可以省去为每个 POCO 类上的所有属性手动映射的麻烦。
以下示例将上面两个派生类索引到一个索引中:通过为基类调用 Map 方法,之后为每个派生类调用 AutoMap 方法:
1 | var createIndexResponse = _client.Indices.Create("myindex", c => c |
以上映射方法所产生的 JSON 结构如下:
1 | { |
以上 JSON 中,NEST 根据 POCOs 属性的数据类型,推断了对应的 ES 数据类型:
-
Birthday:date
-
Hours:long
-
IsManager:boolean
-
Salary:integer
-
Employees:object
-
其余的 string 类型被推断为了 ES 中的 text 类型,且每一个都被标记为了 keyword。
目前 NEST 提供的类型推断映射
支持的 .NET 数据类型
.NET 数据类型 | ES 中的数据类型 |
---|---|
String | text,包含 keyword 子属性,更多关于多字段说明,见此博文 NEST 教程系列 4-7 映射:Multi fields 多字段映射 |
Int32 | integer |
UInt16 | integer |
Int16 | short |
Byte | short |
Int64 | long |
UInt32 | long |
TimeSpan | long |
Single | float |
Double | double |
Decimal | double |
UInt64 | double |
DateTime | date |
DateTimeOffset | date |
Boolean | boolean |
Char | keyword |
Guid | keyword |
-
需要注意:.NET 中的 Decimal 类型在 ES 中没有直接等效的类型,这里用 double 来对应,但存在精度上存在差异(Decimal 精度 小于 Double 精度),在反序列化到 .NET POCO 模型的时候,如果 ES 中的值在 [Decimal.Min, Decimal.Max] 区间范围之外,则在映射到 POCO 模型 Decimal 类型的属性时由于超精度了,就会引发异常。为了避免这种情况,在设计 .NET 模型属性的时候,建议不要用 Decimal 数据类型,转而使用 Double。
NEST 特有的特殊类型映射
NEST 数据类型 | ES 中的数据类型 |
---|---|
Nest.QueryContainer | percolator |
Nest.GeoLocation | geo_point |
Nest.IGeoShape | geo_shape,如果你想要显式映射 shape 类型,则在对应的属性上使用 [Shape]特性 |
Nest.CompletionField | completion |
Nest.DateRange | date_range |
Nest.DoubleRange | double_range |
Nest.FloatRange | float_range |
Nest.IntegerRange | integer_range |
Nest.LongRange | long_range |
Nest.IpAddressRange | ip_range |
除去以上两大类,剩余其他类型默认都被映射为 object。
映射递归
在上面的例子中,Employee 模型内嵌了一个 List
这样设计的目的时为了防止堆栈溢出和无限递归。另外,在大多数情况下,当涉及到 Elasticsearch 映射时,具有这种深层嵌套的映射通常是一个边界情况。但是,会有这样的场景存在,因此你可以通过 .AutoMap(int maxRecursion) 重载方法来指定递归的深度。
示例:
1 | public class A |
直接使用 AutoMap
1 |
|
结果如下:
1 | { |
显式指定 AutoMap 的递归深度为 3:
1 | createIndexResponse = _client.Indices.Create("myindex", c => c |
结果如下:
1 | { |