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; }
}

automapping it

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"
        }
      }
    }
  }
}