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

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

  • 官方文档见此: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 中,多字段映射是很有用的,如:

  • 一个 string 类型的属性会被推断为 ES 的 包含 keyword 子字段的 text 数据类型,其中:

    • text 数据类型适用于全文搜索。
    • keyword 适用于结构搜索、排序以及聚合。
  • 另外多字段映射适用于不同的分析器,以满足不同的全文本搜索需求。

假设有如下模型类:

1
2
3
4
public class Person
{
public string Name { get; set; }
}

string 类型的默认映射

使用 AutoMappin的情况下,在推断 string 类型的映射时,会自动推断出一个包含 keyword 子字段的的多字段文本数据类型:

1
2
3
4
5
var createIndexResponse = _client.Indices.Create("myindex", c => c
.Map<Person>(m => m
.AutoMap()
)
);

结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"mappings": {
"properties": {
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}

使用 text 和 keyword 数据类型来进行全文搜索,排序和聚合:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var searchResponse = _client.Search<Person>(s => s
.Query(q => q
.Match(m => m
.Field(f => f.Name)
.Query("Russ")
)
)
.Sort(ss => ss
.Descending(f => f.Name.Suffix("keyword")) //在 Name 上使用 keyword
)
.Aggregations(a => a
.Terms("peoples_names", t => t
.Field(f => f.Name.Suffix("keyword"))
)
)
);

结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
"query": {
"match": {
"name": {
"query": "Russ"
}
}
},
"sort": [
{
"name.keyword": {
"order": "desc"
}
}
],
"aggs": {
"peoples_names": {
"terms": {
"field": "name.keyword"
}
}
}
}
  • 多字段不会更改 ES 中原始的 _source 字段;

  • 仅影响字段的索引方式。

  • 通过使用 Put Mapping API,可以将新的多字段添加到现有字段中。

创建多字段

通过在创建时候,使用 Map 方法 中的 .Fields() 方法可以创建多字段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var createIndexResponse = _client.Indices.Create("myindex", c => c
.Map<Person>(m => m
.Properties(p => p
.Text(t => t
.Name(n => n.Name)
.Fields(ff => ff
.Text(tt => tt
.Name("stop") //在这个子字段上使用 停用词过滤器
.Analyzer("stop")
)
.Text(tt => tt
.Name("shingles")
.Analyzer("name_shingles") //使用自定义的名为 named_shingles 过滤器
)
.Keyword(k => k
.Name("keyword")
.IgnoreAbove(256)
)
)
)
)
)
);

mapping 信息如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
"mappings": {
"properties": {
"name": {
"type": "text",
"fields": {
"stop": {
"type": "text",
"analyzer": "stop"
},
"shingles": {
"type": "text",
"analyzer": "name_shingles"
},
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}