NEST教程系列:字段映射-自动映射

NEST教程系列:字段映射-自动映射

自动映射

在创建映射时,无论是创建索引还是通过PUT Mapping API, NEST都提供了 Auto Mapping 特性,它可以从要映射的类的属性类型自动推断出正确的Elasticsearch字段数据类型

定义两个类,Company 有一个名称和一组雇员;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; }
}

CompanyEmployee 两个类索引为单个索引,先为基类调用Map,然后对我们想要实现的类型调用AutoMap

var createIndexResponse = _client.Indices.Create("myindex", c => c
    .Map<Document>(m => m
        .AutoMap<Company>() 
        .AutoMap(typeof(Employee)) 
    ));

上述请求JSON如下

{
  "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  已经根据类中属性的CLR类型推断出Elasticsearch类型

属性名 属性类型 Elasticsearch类型
Birthday DateTime Date
Hours TimeSpan long
IsManager bool boolean
Salary int integer
Employees List object
  • 其余的 string 类型被推断为了 ES 中的 text 类型,且每一个都被标记为了 keyword

数据类型映射

支持的 .NET 数据类型

.NET数据类型 Elasticsearch数据类型
String/string text,包含 keyword 子属性
Int32/int integer
UInt16/ushort integer
Int16/short short
Byte/byte short
Int64/long long
UInt32/uint long
TimeSpan long
Single/float float
Double/double double
Decimal/decimal double
UInt64/ulong double
DateTime date
DateTimeOffset date
Boolean/bool boolean
Char/char keyword
Guid keyword
  • 需要注意:.NET 中的 Decimal/decimal 类型在 ES 中没有直接等效的类型,这里用 double 来对应,但存在精度上存在差异(Decimal 精度 小于 Double 精度),在反序列化到 .NET 类的时候,如果 ES 中的值在 [Decimal.Min, Decimal.Max] 区间范围之外,则在映射到 POCO 模型 Decimal 类型的属性时由于超精度了,就会引发异常。为了避免这种情况,在设计 .NET 模型属性的时候,建议不要用 Decimal 数据类型,转而使用 Double。

NEST 特有的特殊类型映射

NEST 数据类型 Elasticsearch数据类型
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

递归映射

如果您注意到在前面的 CompanyEmployee 示例中,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()));

映射后的JSON,仅递归调用了1次

{
  "mappings": {
    "properties": {
      "child": {
        "properties": {},
        "type": "object"
      }
    }
  }}

修改递归次数为3次

createIndexResponse = _client.Indices.Create("myindex", c => c
    .Map<A>(m => m.AutoMap(3)));

映射后的JSON,修改后调用了3次

{
  "mappings": {
    "properties": {
      "child": {
        "type": "object",
        "properties": {
          "child": {
            "type": "object",
            "properties": {
              "child": {
                "type": "object",
                "properties": {
                  "child": {
                    "type": "object",
                    "properties": {}
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

🚀官网传送门

posted @ 2020-07-10 17:42  天盛  阅读(803)  评论(0编辑  收藏  举报