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

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

  • 官方文档见此: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描述了文档的路径。在NEST中,除了生成分别带有 Index,Type 和 Id 类型的构造函数外,还有一个构造函数允许你使用 DocumentPath 类型的实例更简洁地描述文档的路径。

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

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

你也可以指定 Index 的名字:

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

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

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

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

  • 官方文档见此: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


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

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

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

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

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

在 lambda 表达式上追加后缀

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

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

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

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

  • 官方文档见此: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 接口在使用的时候会希望知道字段在原始文档中的路径(以字符串的形式),NEST 提供了 Field 类来允许你获得这些字段路径字符串。

构造函数

通过使用 Field 的构造函数:

1
2
3
4
5
6
7
8
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 文档标识推断

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

  • 官方文档见此: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 方法:

假设你有如下类:

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

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

  • 官方文档见此: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


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 类型。

Elasticsearch.Nest 教程系列 8 聚合:Writing Aggregations | 使用聚合

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

  • 官方文档见此: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


可以简单将 ES 中的聚合和 Sql server 中的“聚合函数(如 SUM,COUNT 等”)相关联。聚合可以嵌套,通过聚合可以找出某个字段的最大值,最小值,平均值,以及对字段进行求和操作等复杂数据的构建。

另外,ES 还提出了 buckets(桶) 这个概念,你可以简单理解为相当于是 Sql server 中的分组(GROUP BY),即在 ES 中的称 GROUP BY 为“分桶”。

关于 Elasticsearch 中的聚合说明,可以见此

编写聚合

Nest 提供了 3 种方式来让你使用聚合:

  • 通过 lambda 表达式的方式。

  • 通过内建的请求对象 AggregationDictionary。

  • 通过结合二元运算符来简化 AggregationDictionary 的使用。

假设有以下 Project 类:

1
2
3
4
5
public class Project
{
public string Name { get; set; }
public int Quantity { get; set; }
}

三种方式的请求命令见下方:

Elasticsearch.Nest 教程系列 7-3 搜索:Selecting fields to return | 选择需要返回的字段

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

  • 官方文档见此: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


有的时候你不需要文档中的所有字段进行返回,有 2 种方法可以让你只返回文档中的某些字段。

通过 Stored Fields

索引文档时,默认情况下,Elasticsearch 会将最初发送的 JSON 文档存储在名为 _source 的特殊字段中。对于每个匹配,搜索查询返回的文档都是从 Elasticsearch 返回的 _source 字段中解析的。

注意: 禁用 _source 意味着不存储原始 JSON 文档,虽然可以节约磁盘,但会导致某些功能无法使用,如无法被检索,无法使用 Reindex API 和高亮。因此禁用 _source 需要根据你的应用场景谨慎考虑。

在搜索请求是通过 .StoredFields 指定要返回的字段值:

Elasticsearch.Nest 教程系列 7-2 搜索:Writing bool queries | 编写布尔查询

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

  • 官方文档见此: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


在使用查询 DSL 的时候,编写布尔查询命令会很冗长,如使用带有 2 个 should 子句的单个布尔查询:

1
2
3
4
5
6
7
8
9
10
var searchResults = this.Client.Search<Project>(s => s
.Query(q => q
.Bool(b => b
.Should(
bs => bs.Term(p => p.Name, "x"),
bs => bs.Term(p => p.Name, "y")
)
)
)
);

可以相像,如果有多个嵌套布尔查询,最终代码久会长成这样:

为了解决代码冗长的问题,Nest 重写了一元操作符(“!”和“+”)以及二元操作符(“||”和“&&”)

运算符 对应的操作
&& must
|| should
+ filter
! must_not

Elasticsearch.Nest 教程系列 6-2 分析:Testing analyzers | 测试分词器

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

  • 官方文档见此: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


借助 Analyze API,可以方便测试内置/自定义的分词器。

测试内置分词器

通过 Analyze API,可以查看内置分析器是如何分析一段文本。

  • 基于标准分词器

1
2
3
4
var analyzeResponse = _client.Indices.Analyze(a => a
.Analyzer("standard")
.Text("F# is THE SUPERIOR language :)")
);

实际发送的请求如下:

1
2
3
4
5
6
7
POST /_analyze
{
"analyzer": "standard",
"text": [
"F# is THE SUPERIOR language :)"
]
}

响应结果如下:

Elasticsearch.Nest 教程系列 6-1 分析:Writing analyzers | 编写分析器

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

  • 官方文档见此: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


ES 中的“分析”是指将文本(如任何电子邮件的正文)转换为 tokens 或 terms 的过程,这些 tokens 或 terms 被添加到倒排索引中以进行搜索。分析是由分析器执行的,该分析器可以是内置分析器,也可以是自定义的分析器。

分词器由 3 部分组成:

  • Character Filters:处理原始文本,如去除 html。

    • 一般有 0 个或多个
  • Tokenizer:按照规则切分为单词。

    • 一般只有 1 个
  • Token filter:加工切分后的单词,如转小写、删除停用词,增加同义词等。

    • 一般有 0 个或多个