标签:Elasticsearch.Nest系列

Elasticsearch.Nest 教程系列 10-4 常用类型:Union Type | 类型合并


ES 中的某些API参数可以接受多个 JSON 数据结构,例如,搜索请求时对 source 过滤可以接受:

  • bool:可以通过布尔值来禁用 _source 检索。
  • string、string[]:可以使用字符串来设定通配符,以此来控制返回 _source 中的哪些部分。
  • object:一个包含 includs 和 excluds 属性的对象,来分别控制需要在 _source 中需要“包含”和“排除”的部分。

在 NEST 中,可以使用 Union<First,Second> 类型。

隐式转换

Union<TFirst,TSecond>具有隐式运算符,可从 TFirst 或 TSecond 的实例转换为Union<TFirst,TSecond> 的实例:

Union<bool, ISourceFilter> sourceFilterFalse = false;

Union<bool, ISourceFilter> sourceFilterInterface = new SourceFilter
{
    Includes = new [] { "foo.*" }
};

Elasticsearch.Nest 教程系列 10-3 常用类型:Date math expressions | 日期数字表达式


在“查询/过滤”的时候支持使用日期类型的数学表达式。表达式以“锚定”日期开始,该日期可以是现在,也可以是以“||”结尾的日期字符串。它后面可以是一个数学表达式,支持 +,- 和 /(四舍五入)。支持的单位有:

  • y (year)
  • M (month)
  • w (week)
  • d (day)
  • h (hour)
  • m (minute)
  • s (second)

ES 中的 Date Math

常规示例

使用 DateMath 提供的静态方法:

Expect("2020-01-23T00:00:00").WhenSerializing(Nest.DateMath.Anchored(new DateTime(2020,01, 23)));

Elasticsearch.Nest 教程系列 10-2 常用类型:Distance Units | 距离单位


在 ES 的 GEO 相关查询中,你会使用到“距离”这个概念,Nest 提供了 Distance 类来帮助你创建“距离”。

通过 Distance 构造函数

var unitComposed = new Distance(25);
var unitComposedWithUnits = new Distance(25, Nest.DistanceUnit.Meters);

也可以使用指定距离单位的字符串,如下:

Expect("25m")
    .WhenSerializing(unitComposed)
    .WhenSerializing(unitComposedWithUnits);

Elasticsearch.Nest 教程系列 10-1 常用类型:Time Units | 时间单位


当你需要在 ES 中指定时间相关的操作时:如超时时间,持续时间,可以使用 Nest 提供的 Time 数据类型。

Time 构造函数

最长用的方法:

var unitString = new Time("2d");
var unitComposed = new Time(2, Nest.TimeUnit.Day);
var unitTimeSpan = new Time(TimeSpan.FromDays(2));
var unitMilliseconds = new Time(1000 * 60 * 60 * 24 * 2);

Elasticsearch.Nest 教程系列 9-7 转换:Indices Paths | 索引路径


Elasticsearch 中的某些API在请求的 URI 中回需要使用索引名称,索引名称的集合或特殊的 _all 标记(表示所有索引),以指定在哪个(哪些)索引上进行请求。

在 Nest 中,这些索引的名称通过 Indices 类型来进行指定。

显式指定

以下几种类型会隐式转换:

  • string。
  • 逗号分隔的 string。
  • string 数组。
  • 已经在 ConnectionSettings 上设置相关类型的索引名称的 CLR 类。
  • IndexName 类
  • IndexName 数组

Elasticsearch.Nest 教程系列 9-6 转换:Document paths | 文档路径


Elasticsearch中的许多API描述了文档的路径。在NEST中,除了生成分别带有 Index,Type 和 Id 类型的构造函数外,还有一个构造函数允许你使用 DocumentPath 类型的实例更简洁地描述文档的路径。

eg:创建一个基于 Project 类的 Document,Id=1

IDocumentPath path = new DocumentPath<Project>(1);

你也可以指定 Index 的名字:

var path = new DocumentPath<Project>(1).Index("project1");

通过 DocumentPath 静态方法来进行指定:

Elasticsearch.Nest 教程系列 9-5 转换:Property name inference | 属性名推断


在 lambda 表达式 “主体” 上追加后缀

可以将后缀追加到 lambda 表达式的主体上,这在以下情况下很有用:

  • 将POCO属性映射为多字段,并且希望对 lambda 表达式使用强类型访问:将后缀追加到生成的字段名称中,以便访问多字段的特定子字段。

.Suffix() 扩展方法可用于此目的,并且当序列化以此方式追加后缀的表达式时,序列化的属性名称将解析为最后一个标记:

Expression<Func<Project, object>> expression = p => p.Name.Suffix("raw");
Expect("raw").WhenSerializing<PropertyName>(expression);

在 lambda 表达式上追加后缀

可以使用.ApplySuffix() 扩展方法将后缀直接应用于 lambda 表达式:

Expression<Func<Project, object>> expression = p => p.Name;
expression = expression.AppendSuffix("raw");
Expect("raw").WhenSerializing<PropertyName>(expression);

Elasticsearch.Nest 教程系列 9-4 转换:Field inference | 字段推断


不少 Elasticsearch API 接口在使用的时候会希望知道字段在原始文档中的路径(以字符串的形式),NEST 提供了 Field 类来允许你获得这些字段路径字符串。

构造函数

通过使用 Field 的构造函数:

var fieldString = new Field("name");

//使用重载方法
var fieldProperty = new Field(typeof(Project).GetProperty(nameof(Project.Name)));

//使用 lambda 表达式的方式
Expression<Func<Project, object>> expression = p => p.Name;
var fieldExpression = new Field(expression);

你也可以在实例化的时候设定 boost 值。

eg:当你使用如下构造函数时:

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 方法:

假设你有如下类:

Elasticsearch.Nest 教程系列 9-2 转换:Relation names inference | 关系名推断


当你使用子父级关系的时候,需要将子父级文档索引(添加)到同一个索引中,在 ES 5.x 的时候,你可以通过 / 中的 来进行指定,但从 ES7 开始,已经没有 type 一说(type=_doc),这个时候,你需要用 RelationName 来进行代替。

var settings = new ConnectionSettings()
    .DefaultMappingFor<CommitActivity>(m => m
        .IndexName("projects-and-commits")
        .RelationName("commits")
    )
    .DefaultMappingFor<Project>(m => m
        .IndexName("projects-and-commits")
        .RelationName("projects")
    );

var resolver = new RelationNameResolver(settings);
var relation = resolver.Resolve<Project>();
relation.Should().Be("projects");

relation = resolver.Resolve<CommitActivity>();
relation.Should().Be("commits");
  • RelationName 通过 DefaultTypeNameInferrer 使用一个 string 来表示转换后的 CLR 类型。
  • 显式的配置 TypeName 不会影响原始 CLR 类型。