【问题标题】:ElasticSearch 2.x attribute mapping ignores "NotAnalyzed"ElasticSearch 2.x 属性映射忽略“NotAnalyzed”
【发布时间】:2016-12-01 02:10:43
【问题描述】:

我正在尝试将我的应用程序从 ElasticSearch Nest 1.7 升级到 2.4,并且基于属性的映射看起来应该可以工作,但它(完全)没有。我有一个这样的模型类:

[DataContract]
[ElasticsearchType(IdProperty = "Id")]
public class Series
{
    [DataMember]
    [String(Index = FieldIndexOption.Analyzed, Analyzer = "custom_en")]
    public string Description { get; set; }

    [DataMember]
    [String(Index = FieldIndexOption.NotAnalyzed)]
    public HashSet<Role> ReleasableTo { get; set; }
}

Nest 1.x 中的等效声明正在工作,我对该字段的术语查询返回了我期望的结果。当我没有收到任何结果时,我检查了映射,令我惊讶的是,Index = FieldIndexOption.NotAnalyzed 没有得到尊重。我生成的映射是这样的:

"properties" : {
    "description" : {
        "type": "string"
    }
    "releasableTo" : {
        "type": "string"
    }
}

因此,我设置了自定义分析器的字段都没有正确标记,我不需要分析的字段也没有正确标记。

这是我用来初始化一切的代码:

            var indexDescriptor = new CreateIndexDescriptor(DefaultIndex)
                .Mappings(ms => ms
                    .Map<Series>(m => m.AutoMap())
                )
            );

            indexDescriptor.Settings(s => s
                .NumberOfShards(3)
                .NumberOfReplicas(2)
                .Analysis(a => a
                    .CharFilters(c => c.Mapping("&_to_and", mf => mf.Mappings( "&=> and ")))
                    .TokenFilters(t => t.Stop("en_stopwords", tf=>tf.StopWords(new StopWords(stopwords)).IgnoreCase()))
                    .Analyzers(z => z
                        .Custom("custom_en", ca => ca
                            .CharFilters("html_strip", "&_to_and")
                            .Tokenizer("standard")
                            .Filters("lowercase", "en_stopwords")
                        )
                    )
                )
            );

            client.CreateIndex(indexDescriptor);

注意:client 是 elasticsearch 客户端。

我知道DataContract 属性并不严格适用于 ElasticSearch,但我还需要将这些对象序列化到磁盘进行处理。使用 Nest 1.x 没有冲突,因此不会造成任何问题。

我不关心分析器的创建。我担心映射不尊重比类型更具体的任何东西。

如何让 Nest 2.x 尊重属性中的附加信息,这样我就不必在声明映射时手动映射它们?


因此,映射问题与同时映射的其他类型有关。索引中有一个无效的响应,我没有捕捉到。完成工作非常令人沮丧,但现在映射工作正常。

【问题讨论】:

  • 注意:修正了@RussCam 在他的回答中指出的错字。

标签: c# nest elasticsearch-2.0


【解决方案1】:

我不确定这是否是拼写错误,但您的属性类型是 Series,但您正在映射类型 Service

我无法使用 NEST 2.5.0 重现您所看到的内容。这是一个完整的例子

void Main()
{
    var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
    var defaultIndex = "default-index";
    var connectionSettings = new ConnectionSettings(pool, new InMemoryConnection())
            .DefaultIndex(defaultIndex)
            .PrettyJson()
            .DisableDirectStreaming()
            .OnRequestCompleted(response =>
                {
                    // log out the request
                    if (response.RequestBodyInBytes != null)
                    {
                        Console.WriteLine(
                            $"{response.HttpMethod} {response.Uri} \n" +
                            $"{Encoding.UTF8.GetString(response.RequestBodyInBytes)}");
                    }
                    else
                    {
                        Console.WriteLine($"{response.HttpMethod} {response.Uri}");
                    }

                    Console.WriteLine();

                    // log out the response
                    if (response.ResponseBodyInBytes != null)
                    {
                        Console.WriteLine($"Status: {response.HttpStatusCode}\n" +
                                 $"{Encoding.UTF8.GetString(response.ResponseBodyInBytes)}\n" +
                                 $"{new string('-', 30)}\n");
                    }
                    else
                    {
                        Console.WriteLine($"Status: {response.HttpStatusCode}\n" +
                                 $"{new string('-', 30)}\n");
                    }
                });

    var client = new ElasticClient(connectionSettings);

    var stopwords = "stopwords";

    var indexDescriptor = new CreateIndexDescriptor(defaultIndex)
        .Mappings(ms => ms
            .Map<Series>(m => m.AutoMap())
        );

    indexDescriptor.Settings(s => s
        .NumberOfShards(3)
        .NumberOfReplicas(2)
        .Analysis(a => a
            .CharFilters(c => c.Mapping("&_to_and", mf => mf.Mappings("&=> and ")))
            .TokenFilters(t => t.Stop("en_stopwords", tf => tf.StopWords(new StopWords(stopwords)).IgnoreCase()))
            .Analyzers(z => z
                .Custom("custom_en", ca => ca
                    .CharFilters("html_strip", "&_to_and")
                    .Tokenizer("standard")
                    .Filters("lowercase", "en_stopwords")
                )
            )
        )
    );

    client.CreateIndex(indexDescriptor);

}

[DataContract]
[ElasticsearchType(IdProperty = "Id")]
public class Series
{
    [DataMember]
    [String(Index = FieldIndexOption.Analyzed, Analyzer = "custom_en")]
    public string Description { get; set; }

    [DataMember]
    [String(Index = FieldIndexOption.NotAnalyzed)]
    public HashSet<Role> ReleasableTo { get; set; }
}

这使用InMemoryConnection,因此不会向 Elasticsearch 发出请求(可以删除它以实际发送请求)。创建索引请求看起来像

{
  "settings": {
    "index.number_of_replicas": 2,
    "index.number_of_shards": 3,
    "analysis": {
      "analyzer": {
        "custom_en": {
          "type": "custom",
          "char_filter": [
            "html_strip",
            "&_to_and"
          ],
          "filter": [
            "lowercase",
            "en_stopwords"
          ],
          "tokenizer": "standard"
        }
      },
      "char_filter": {
        "&_to_and": {
          "type": "mapping",
          "mappings": [
            "&=> and "
          ]
        }
      },
      "filter": {
        "en_stopwords": {
          "type": "stop",
          "stopwords": "stopwords",
          "ignore_case": true
        }
      }
    }
  },
  "mappings": {
    "series": {
      "properties": {
        "description": {
          "type": "string",
          "index": "analyzed",
          "analyzer": "custom_en"
        },
        "releasableTo": {
          "type": "string",
          "index": "not_analyzed"
        }
      }
    }
  }
}

具有各自的属性映射。请记住,如果索引已经存在,则不会应用映射更改,因此在这种情况下您需要删除并创建索引。

【讨论】:

  • 这是一个错字,因为我删除了所有我认为与我的问题相关的内容。我需要自动映射多种类型,Service 是另一种类型。我会仔细检查列表,以确保我没有在我的代码中映射相同的东西两次或完全丢失 Series....
  • 作为旁注,我从嵌入文件中读取了换行分隔的停用词列表(对于手头的问题并不重要),以清除那些使搜索结果不太有用的东西。我相信你知道这一点,但我是为其他人发表声明,稍后会来阅读你的代码。
  • 好的,当我创建索引时,由于其他类型的异常,看起来映射被破坏了。
猜你喜欢
  • 1970-01-01
  • 2017-02-19
  • 1970-01-01
  • 2017-12-31
  • 2011-06-26
  • 2016-08-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多