ElasticSearch 5 按关键字字段排序不区分大小写
ElasticSearch 5 Sort by Keyword Field Case Insensitive
我们正在使用 ElasticSearch 5。
我有一个字段 city
使用自定义分析器和以下映射。
分析仪
"analysis": {
"analyzer": {
"lowercase_analyzer": {
"filter": [
"standard",
"lowercase",
"trim"
],
"type": "custom",
"tokenizer": "keyword"
}
}
映射
"city": {
"type": "text",
"analyzer": "lowercase_analyzer"
}
我这样做是为了对城市字段进行不区分大小写的排序。这是我尝试 运行
的示例查询
{
"query": {
"term": {
"email": {
"value": "some_email@test.com"
}
}
},
"sort": [
{
"city": {
"order": "desc"
}
}
]
}
这是我收到的错误:
"Fielddata is disabled on text fields by default. Set fielddata=true
on [city] in order to load fielddata in memory by uninverting the
inverted index. Note that this can however use significant memory."
我不想打开 FieldData
并导致 ElasticSearch 性能下降。我想要一个不区分大小写的 Keyword
字段,以便我可以对其执行更有意义的聚合和排序。有没有办法做到这一点?
是的,有一种方法可以做到这一点,使用 multi_fields
。
在 Elasticsearch 5.0 及更高版本中,string
field types were split out into two separate types, text
field types that are analyzed and can be used for search, and keyword
未分析且适合用于排序、聚合和精确值匹配的字段类型。
在 Elasticsearch 5.0 中使用动态映射(即让 Elasticsearch 推断文档 属性 应该映射到的类型),json string
属性 被映射到 text
字段类型,子字段 "keyword" 映射为 keyword
字段类型和设置 ignore_above:256
.
使用 NEST 5.x 自动映射,您的 POCO 上的 string
属性 将以与 Elasticsearch 中的动态映射相同的方式自动映射,如上所示给定以下文件
public class Document
{
public string Property { get; set; }
}
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var defaultIndex = "default-index";
var connectionSettings = new ConnectionSettings(pool)
.DefaultIndex(defaultIndex);
var client = new ElasticClient(connectionSettings);
client.CreateIndex(defaultIndex, c => c
.Mappings(m => m
.Map<Document>(mm => mm
.AutoMap()
)
)
);
产生
{
"mappings": {
"document": {
"properties": {
"property": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
}
}
}
}
}
您现在可以使用 property
使用 Field(f => f.Property.Suffix("keyword")
进行排序。查看 Field Inference 以获取更多示例。
keyword
字段类型默认启用 doc_values
,这意味着列式数据结构是在索引时构建的,这就是提供高效排序和聚合的原因。
要在创建索引时添加自定义分析器,我们可以像以前一样自动映射,但随后会为我们想要使用 .Properties()
控制映射的字段提供覆盖
client.CreateIndex(defaultIndex, c => c
.Settings(s => s
.Analysis(a => a
.Analyzers(aa => aa
.Custom("lowercase_analyzer", ca => ca
.Tokenizer("keyword")
.Filters(
"standard",
"lowercase",
"trim"
)
)
)
)
)
.Mappings(m => m
.Map<Document>(mm => mm
.AutoMap()
.Properties(p => p
.Text(t => t
.Name(n => n.Property)
.Analyzer("lowercase_analyzer")
.Fields(f => f
.Keyword(k => k
.Name("keyword")
.IgnoreAbove(256)
)
)
)
)
)
)
);
产生
{
"settings": {
"analysis": {
"analyzer": {
"lowercase_analyzer": {
"type": "custom",
"filter": [
"standard",
"lowercase",
"trim"
],
"tokenizer": "keyword"
}
}
}
},
"mappings": {
"document": {
"properties": {
"property": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
},
"analyzer": "lowercase_analyzer"
}
}
}
}
}
我们正在使用 ElasticSearch 5。
我有一个字段 city
使用自定义分析器和以下映射。
分析仪
"analysis": {
"analyzer": {
"lowercase_analyzer": {
"filter": [
"standard",
"lowercase",
"trim"
],
"type": "custom",
"tokenizer": "keyword"
}
}
映射
"city": {
"type": "text",
"analyzer": "lowercase_analyzer"
}
我这样做是为了对城市字段进行不区分大小写的排序。这是我尝试 运行
的示例查询{
"query": {
"term": {
"email": {
"value": "some_email@test.com"
}
}
},
"sort": [
{
"city": {
"order": "desc"
}
}
]
}
这是我收到的错误:
"Fielddata is disabled on text fields by default. Set fielddata=true on [city] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory."
我不想打开 FieldData
并导致 ElasticSearch 性能下降。我想要一个不区分大小写的 Keyword
字段,以便我可以对其执行更有意义的聚合和排序。有没有办法做到这一点?
是的,有一种方法可以做到这一点,使用 multi_fields
。
在 Elasticsearch 5.0 及更高版本中,string
field types were split out into two separate types, text
field types that are analyzed and can be used for search, and keyword
未分析且适合用于排序、聚合和精确值匹配的字段类型。
在 Elasticsearch 5.0 中使用动态映射(即让 Elasticsearch 推断文档 属性 应该映射到的类型),json string
属性 被映射到 text
字段类型,子字段 "keyword" 映射为 keyword
字段类型和设置 ignore_above:256
.
使用 NEST 5.x 自动映射,您的 POCO 上的 string
属性 将以与 Elasticsearch 中的动态映射相同的方式自动映射,如上所示给定以下文件
public class Document
{
public string Property { get; set; }
}
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var defaultIndex = "default-index";
var connectionSettings = new ConnectionSettings(pool)
.DefaultIndex(defaultIndex);
var client = new ElasticClient(connectionSettings);
client.CreateIndex(defaultIndex, c => c
.Mappings(m => m
.Map<Document>(mm => mm
.AutoMap()
)
)
);
产生
{
"mappings": {
"document": {
"properties": {
"property": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
}
}
}
}
}
您现在可以使用 property
使用 Field(f => f.Property.Suffix("keyword")
进行排序。查看 Field Inference 以获取更多示例。
keyword
字段类型默认启用 doc_values
,这意味着列式数据结构是在索引时构建的,这就是提供高效排序和聚合的原因。
要在创建索引时添加自定义分析器,我们可以像以前一样自动映射,但随后会为我们想要使用 .Properties()
client.CreateIndex(defaultIndex, c => c
.Settings(s => s
.Analysis(a => a
.Analyzers(aa => aa
.Custom("lowercase_analyzer", ca => ca
.Tokenizer("keyword")
.Filters(
"standard",
"lowercase",
"trim"
)
)
)
)
)
.Mappings(m => m
.Map<Document>(mm => mm
.AutoMap()
.Properties(p => p
.Text(t => t
.Name(n => n.Property)
.Analyzer("lowercase_analyzer")
.Fields(f => f
.Keyword(k => k
.Name("keyword")
.IgnoreAbove(256)
)
)
)
)
)
)
);
产生
{
"settings": {
"analysis": {
"analyzer": {
"lowercase_analyzer": {
"type": "custom",
"filter": [
"standard",
"lowercase",
"trim"
],
"tokenizer": "keyword"
}
}
}
},
"mappings": {
"document": {
"properties": {
"property": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
},
"analyzer": "lowercase_analyzer"
}
}
}
}
}