2016-12-14 3 views
0

Я пытаюсь использовать динамический шаблон в ES, чтобы все строковые поля были multifields. Я также хочу применить некоторые определенные сопоставления к определенным полям.ElasticSearch Nest: AutoMap с DynamicTemplates

Возьмем следующий пример класса:

[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 действительно верно, но multifield1 и multifield2 неверны (это не много полей).

Обход

Я знаю, что могу «исправить» это, НЕ делать AutoMap() и вместо указания каждого из специальных индексов, но есть много полей, и что не так чист раствора.

Могу ли я сделать AutoMap с помощью DynamicTemplates?

ответ

2

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. NEST 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" 
    } 
    } 
} 
+1

ДА! Спасибо, Русс, образец кода с шаблоном посетителя отлично работал. Я изменил его для ES 2.x вместо 5.x, и все выглядит хорошо. Ты жжешь! – jhilden

Смежные вопросы