标签:Elasticsearch

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


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

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

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

编写聚合

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

  • 通过 lambda 表达式的方式。
  • 通过内建的请求对象 AggregationDictionary。
  • 通过结合二元运算符来简化 AggregationDictionary 的使用。

假设有以下 Project 类:

public class Project
{
    public string Name { get; set; }
    public int Quantity { get; set; }
}

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

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


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

通过 Stored Fields

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

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

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

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


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

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 | 测试分词器


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

测试内置分词器

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

  • 基于标准分词器

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

实际发送的请求如下:

POST /_analyze
{
    "analyzer": "standard",
    "text": [
        "F# is THE SUPERIOR language :)"
    ]
}

响应结果如下:

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


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

分词器由 3 部分组成:

  • Character Filters:处理原始文本,如去除 html。
    • 一般有 0 个或多个
  • Tokenizer:按照规则切分为单词。
    • 一般只有 1 个
  • Token filter:加工切分后的单词,如转小写、删除停用词,增加同义词等。
    • 一般有 0 个或多个

Elasticsearch.Nest 教程系列 5-3 索引:Ingest Pipeline | Ingest 管道


Ingest 管道是一系列按照声明的顺序执行的处理器。

假设有以下 POCO 类:

public class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string IpAddress { get; set; }
    public GeoIp GeoIp { get; set; }
}

public class GeoIp
{
    public string CityName { get; set; }
    public string ContinentName { get; set; }
    public string CountryIsoCode { get; set; }
    public GeoLocation Location { get; set; }
    public string RegionName { get; set; }
}

创建一个 Ingestion 管道:
eg:假设为 Person 文档建立索引,创建一个 Ingestion 管道,在被索引到 ES 之前对其进行相关操作:

  • 将 LastName 转换为大写
  • 将姓名的首字母索引到其他字段—这里用 initials 字段
  • 将 IpAddress 转换为具体地址。

Elasticsearch.Nest 教程系列 5-2 索引:Ingest Node | 使用 Ingest 节点


Ingest Node 的作用

在文档索引发生之前,会使用 Ingest 节点进行预处理文档。Ingest 节点会拦截批量和索引请求,之后应用转换(mapping),然后将文档传递回索引或 Bulk API。

  • 即:在数据被索引之前,通过预定义好的处理管道对数据进行预处理。

默认情况下,所有节点都启用 Ingest,也就是说任何节点都可以处理 Ingest 任务。

  • 当然,你也可以创建某些业务专用的 Ingest 节点。

Elasticsearch 会将自动将索引请求重新路由到 Ingest 节点,而您可以优化此路径。

Elasticsearch.Nest 教程系列 5-1 索引:Indexing | 索引(添加)文档


索引(Indexing):是指讲文档添加到 ES 中的过程,目前 Nest 提供了以下 3 种 Indexing 方式:

  • Indexing Documents
  • Ingest Node
  • Ingest Pipelines

NEST 提供了多种索引文档的方式:

假设有 Person 类:

public class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Elasticsearch.Nest 教程系列 4-7 映射:Multi fields | 多字段映射


在 ES 中,多字段映射是很有用的,如:

  • 一个 string 类型的属性会被推断为 ES 的 包含 keyword 子字段的 text 数据类型,其中:
    • text 数据类型适用于全文搜索。
    • keyword 适用于结构搜索、排序以及聚合。
  • 另外多字段映射适用于不同的分析器,以满足不同的全文本搜索需求。

假设有如下模型类:

public class Person
{
    public string Name { get; set; }
}

Elasticsearch.Nest 教程系列 4-6 映射:Ignoring properties | 映射时忽略 POCO 上的某些属性


POCO 类属性进行映射时,可以通过以下几种方式忽略部分属性

  • 在使用继承了 ElasticsearchPropertyAttributeBase 的各特性上使用 Ignore 属性:如在使用 TextAttribute 时,使用 Ingore 属性进行属性忽略。
  • 在使用 PropertyNameAttribute 的时候使用Ignore属性。
  • 使用 ConnectionSettings.DefaultMappingFor(Func<ClrTypeMappingDescriptor,
    IClrTypeMapping> selector) 方法的时候进行指定需要忽略的属性。
  • 使用能够被 IElasticsearchSerializer 识别的 Ignore 特性,内建的 SourceSerializer 可以使用 [IgnoreAttribute] 进行忽略。

忽略类中的部分属性

示例: