ElasticSearch 5按关键字字段大小写排序不敏感

时间:2016-12-09 15:41:41

标签: elasticsearch nest

我们正在使用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。设置fielddata = true   在[city]上通过uninverting来加载内存中的fielddata   倒指数。请注意,这可能会占用大量内存。"

我不想打开FieldData并在ElasticSearch中产生性能影响。我希望Keyword字段不区分大小写,以便我可以对其执行更有意义的聚合和排序。有没有办法做到这一点?

1 个答案:

答案 0 :(得分:2)

是的,有一种方法可以使用multi_fields

在Elasticsearch 5.0之后,string field types were split out分为两种不同的类型,text字段类型,经过分析并可用于搜索,以及keyword字段类型未分析且适合用于排序,聚合和精确值匹配。

使用Elasticsearch 5.0中的动态映射(即让Elasticsearch推断应该将文档属性映射到的类型),将json string属性映射到text字段类型,并使用子字段"关键字"它被映射为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"
        }
      }
    }
  }
}