前言
使用NEST
与Elasticsearch进行交互,我们需要知道C#中的实体类型数据是如何转换成JSON文档并存储在Elasticsearch中的。接下来的这一章节,我们将介绍NEST
与Elasticsearch之间不同的实体映射方式。
NEST
提供了几种处理C#数据类型与Elasticsearch数据类型之间映射关系的方法,包括:自动映射(Auto mapping
),特性映射(Attribute mapping
),链式映射(Fluent mapping
),访问者模式映射(Visitor pattern
)和父子关系映射(Parent/Child relationships
)等。
本节将为大家分享的是自动映射(Auto mapping
)。
自动映射
无论通过Create
方法或PutMapping
方法创建映射时, NEST
均提供了自动映射的特性,它可以自动地从CLR POCO属性类型推断对应的正确的Elasticsearch字段数据类型。
我们将通过一系列的示例来学习NEST
的自动映射。为此,我们定义两个实例,分别为Company
实体(它包含了一个Name
字符串属性成员以及一个Employees
集合属性成员)和Employee
实体(它包含了多个不同数据类型的属性成员以及一个自包含的Employee
集合),示例代码如下:
public abstract class Document
{
public JoinField Join { get; set; }
}
public class Company : Document
{
public string Name { get; set; }
public List<Employee> Employees { get; set; }
}
public class Employee : Document
{
public string LastName { get; set; }
public int Salary { get; set; }
public DateTime Birthday { get; set; }
public bool IsManager { get; set; }
public List<Employee> Employees { get; set; }
public TimeSpan Hours { get; set; }
}
自动映射可以省去为实体上的所有属性定义手动映射的麻烦。在本例中,我们希望将两个子类索引到一个索引中。我们为基类调用Map
方法,然后为其中的成员调用AutoMap
方法,示例如下:
var createIndexResponse = _client.Indices.Create("myindex", c => c
.Map<Document>(m => m
.AutoMap<Company>()
.AutoMap(typeof(Employee))
)
);
生成的Elasticsearch映射结果为:
{
"mappings": {
"properties": {
"birthday": {
"type": "date"
},
"employees": {
"properties": {
"birthday": {
"type": "date"
},
"employees": {
"properties": {},
"type": "object"
},
"hours": {
"type": "long"
},
"isManager": {
"type": "boolean"
},
"join": {
"properties": {},
"type": "object"
},
"lastName": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"salary": {
"type": "integer"
}
},
"type": "object"
},
"hours": {
"type": "long"
},
"isManager": {
"type": "boolean"
},
"join": {
"properties": {},
"type": "object"
},
"lastName": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"name": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"salary": {
"type": "integer"
}
}
}
}
从JSON结果可以看到,NEST
基于POCO属性的CLR类型推断出了Elasticsearch类型。在本示例中:
Birthday
被映射成了date
数据类型Hours
被映射成了long
数据类型IsManager
被映射成了boolean
Salary
被映射成了integer
数据类型Employees
被映射成了object
数据类型
其余的字符串属性作为多字段text
数据类型,每个都有一个keyword
数据类型子字段。
.NET与Elasticsearch的数据类型映射关系
NEST为以下.NET类型提供了推断映射支持:
.NET数据类型 | Elasticsearch数据类型 |
---|---|
String |
maps to "text" with a "keyword" sub field. See Multi Fields. |
Int32 |
maps to "integer" |
UInt16 |
maps to "integer" |
Int16 |
maps to "short" |
Byte |
maps to "short" |
Int64 |
maps to "long" |
UInt32 |
maps to "long" |
TimeSpan |
maps to "long" |
Single |
maps to "float" |
Double |
maps to "double" |
Decimal |
maps to "double" |
UInt64 |
maps to "double" |
DateTime |
maps to "date" |
DateTimeOffset |
maps to "date" |
Boolean |
maps to "boolean" |
Char |
maps to "keyword" |
Guid |
maps to "keyword" |
另外,NEST
还内置了一些特殊的映射:
.NET数据类型 | Elasticsearch数据类型 |
---|---|
Nest.QueryContainer |
maps to "percolator" |
Nest.GeoLocation |
maps to "geo_point" |
Nest.IGeoShape |
maps to "geo_shape" (if you want to map to a "shape" type use explicit mapping or the [Shape] attribute on the property) |
Nest.CompletionField |
maps to "completion" |
Nest.DateRange |
maps to "date_range" |
Nest.DoubleRange |
maps to "double_range" |
Nest.FloatRange |
maps to "float_range" |
Nest.IntegerRange |
maps to "integer_range" |
Nest.LongRange |
maps to "long_range" |
Nest.IpAddressRange |
maps to "ip_range" |
默认情况下,以上列举之外的数据类型都将被映射成object
。
循环映射
细心的你可能已经注意到,在前面的示例中,Employee
类型是递归的,因为Employee
类本身包含一个Employee
类型的集合。默认情况下,.AutoMap()
在遇到像这样的递归实例时只会遍历一级深度,Employee
类上的Employee
集合并没有任何属性映射。
这样做的目的是为了防止堆栈溢出和无限递归带的问题。但是在大多数情况下,当涉及到Elasticsearch映射时,通常会出现这样的深度嵌套映射。你可能需要嵌套多级的递归深度。这时,你可以使用AutoMap()
的参数来控制递归的深度。
比如下面有一个非常简单的类A
,它自包含了一个属性A
成员,如下:
public class A
{
public A Child { get; set; }
}
默认情况下,.AutoMap()
只会递归一级的深度:
var createIndexResponse = _client.Indices.Create("myindex", c => c
.Map<A>(m => m.AutoMap())
);
得到的Elasticsearch映射关系如下:
{
"mappings": {
"properties": {
"child": {
"properties": {},
"type": "object"
}
}
}
}
现在,我们使用.AutoMap(3)
来指定递归的层级为3层,如下:
createIndexResponse = _client.Indices.Create("myindex", c => c
.Map<A>(m => m.AutoMap(3))
);
得到的Elasticsearch映射关系如下:
{
"mappings": {
"properties": {
"child": {
"type": "object",
"properties": {
"child": {
"type": "object",
"properties": {
"child": {
"type": "object",
"properties": {
"child": {
"type": "object",
"properties": {}
}
}
}
}
}
}
}
}
}
}
发表评论
登录用户才能发表评论, 请 登 录 或者 注册