ElasticSearch Nest:使用DynamicTemplates的AutoMap

问题描述 投票:0回答:1

我正在尝试在ES中使用动态模板,以便所有字符串字段都是多字段。我还想对某些字段应用一些特定的映射。

采用以下示例类:

[ElasticsearchType(Name = "sample1")]
public class Sample1
{
    public string ID { get; set; }

    [String(Index = FieldIndexOption.No)]
    public string DoNotIndex { get; set; }

    public string MultiField1 { get; set; }

    public string MultiField2 { get; set; }
}

我想创建动态模板,并使用以下命令将映射应用于DoNotIndex

_client.Map<Sample1>(m => m
  .AutoMap()
  .DynamicTemplates(dt=> dt
      .DynamicTemplate("all_strings_multifields", t => t
        .MatchMappingType("string")
        .Mapping(tm => tm
            .String(mf => mf
                .Index(FieldIndexOption.Analyzed)
                .Fields(mff => mff
                    .String(s => s
                        .Name("raw")
                        .Index(FieldIndexOption.NotAnalyzed)
                    )
                )
            )
        )
    )
    )
)
.VerifySuccessfulResponse();

结果是:

{
  "test1": {
    "mappings": {
      "sample1": {
        "dynamic_templates": [
          {
            "all_strings_multifields": {
              "match_mapping_type": "string",
              "mapping": {
                "fields": {
                  "raw": {
                    "type": "string",
                    "index": "not_analyzed"
                  }
                },
                "index": "analyzed",
                "type": "string"
              }
            }
          }
        ],
        "properties": {
          "doNotIndex": {
            "type": "keyword",
            "index": false
          },
          "iD": {
            "type": "text"
          },
          "multiField1": {
            "type": "text"
          },
          "multiField2": {
            "type": "text"
          }
        }
      }
    }
  }
}

Results

你会看到DoNotIndex属性确实是正确的,但是multifield1multifield2不正确(它们不是多字段)。

Workaround

我知道我可以通过不做AutoMap()来修复这个问题,而是指定每个特殊索引,但是有很多字段,而且不是一个解决方案。

我可以使用动态模板进行AutoMap吗?

elasticsearch nest
1个回答
3
投票

Dynamic templates仅适用于动态添加到映射的字段,因此使用.AutoMap()显式映射的属性不会受到动态映射的影响。

但是,有一种方法可以使用访问者模式将约定应用于与NEST的显式映射。看起来你正在使用Elasticsearch 5.0,so you should use the text and keyword mappings.

首先定义访客

[ElasticsearchType(Name = "sample1")]
public class Sample1
{
    public string ID { get; set; }

    [Keyword(Index = false)]
    public string DoNotIndex { get; set; }

    public string MultiField1 { get; set; }

    public string MultiField2 { get; set; }
}

public class AllStringsMultiFieldsVisitor : NoopPropertyVisitor
{
    public override void Visit(ITextProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute)
    {
        // if a custom attribute has been applied, let it take precedence
        if (propertyInfo.GetCustomAttribute<ElasticsearchPropertyAttributeBase>() == null)
        {
            type.Fields = new Properties
            {
                {
                    "raw", new KeywordProperty()
                }
            };
        }

        base.Visit(type, propertyInfo, attribute);
    }
}

然后将访问者的实例传递给.AutoMap()

client.Map<Sample1>(m => m
    .AutoMap(new AllStringsMultiFieldsVisitor())
    .DynamicTemplates(dt => dt
        .DynamicTemplate("all_strings_multifields", t => t
            .MatchMappingType("text")
            .Mapping(tm => tm
                .Text(mf => mf
                    .Index(true)
                    .Fields(mff => mff
                        .Keyword(s => s
                            .Name("raw")
                        )
                    )
                )
            )
        )
    )
);

产生

{
  "dynamic_templates": [
    {
      "all_strings_multifields": {
        "match_mapping_type": "text",
        "mapping": {
          "type": "text",
          "fields": {
            "raw": {
              "type": "keyword"
            }
          },
          "index": true
        }
      }
    }
  ],
  "properties": {
    "iD": {
      "fields": {
        "raw": {
          "type": "keyword"
        }
      },
      "type": "text"
    },
    "doNotIndex": {
      "type": "keyword",
      "index": false
    },
    "multiField1": {
      "fields": {
        "raw": {
          "type": "keyword"
        }
      },
      "type": "text"
    },
    "multiField2": {
      "fields": {
        "raw": {
          "type": "keyword"
        }
      },
      "type": "text"
    }
  }
}

然而,我应该指出,default automapping for a C# string property in NEST 5.0将它映射为text场与keyword子场与ignore_above:256NEST 5.0 was released to nuget earlier this week

client.Map<Sample1>(m => m
    .AutoMap()
    .DynamicTemplates(dt => dt
        .DynamicTemplate("all_strings_multifields", t => t
            .MatchMappingType("text")
            .Mapping(tm => tm
                .Text(mf => mf
                    .Index(true)
                    .Fields(mff => mff
                        .Keyword(s => s
                            .Name("raw")
                        )
                    )
                )
            )
        )
    )
);

产生

{
  "dynamic_templates": [
    {
      "all_strings_multifields": {
        "match_mapping_type": "text",
        "mapping": {
          "type": "text",
          "fields": {
            "raw": {
              "type": "keyword"
            }
          },
          "index": true
        }
      }
    }
  ],
  "properties": {
    "iD": {
      "fields": {
        "keyword": {
          "ignore_above": 256,
          "type": "keyword"
        }
      },
      "type": "text"
    },
    "doNotIndex": {
      "type": "keyword",
      "index": false
    },
    "multiField1": {
      "fields": {
        "keyword": {
          "ignore_above": 256,
          "type": "keyword"
        }
      },
      "type": "text"
    },
    "multiField2": {
      "fields": {
        "keyword": {
          "ignore_above": 256,
          "type": "keyword"
        }
      },
      "type": "text"
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.