ElasticSearch Nest:使用DynamicTemplates

时间:2016-12-14 22:56:29

标签: elasticsearch nest

我尝试在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"
          }
        }
      }
    }
  }
}

结果

您会发现DoNotIndex属性确实正确,但multifield1multifield2不正确(它们不是多字段)。

解决方法

我知道我可以修复&#34;这通过 NOT 执行AutoMap()而是指定每个特殊索引,但是有很多字段,并且不是解决方案的干净。

我可以使用DynamicTemplates进行AutoMap吗?

1 个答案:

答案 0 :(得分: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:256子字段为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") ) ) ) ) ) ) ); NEST 5.0 was released to nuget earlier this week

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

产生

{{1}}