2016-12-11 5 views
0

außer Kraft setzen:Wie kann ich eine Unterkunft Art und DATAT in ElasticSearch.NET Ich habe wie dieses ein Objekt

public class MyDate { 
    public DateTime Original { get; set; } 
    public string MungedFormatForAnotherSystem { get; set; } 
} 

public class ESClass { 
    public string Id { get;set; } 
    public MyDate LastUpdatedDate {get;set;} 
} 

ich die NEST-Client wie folgt verwenden:

var client = new ElasticClient(); 
client.Index(doc, i => i.Index("myindex"); 

Was ich will, ist für MyDate in ES als nur der Original Teil serialisiert werden, dann für Abfragen auf dasselbe zu tun.

Ich kann das Objekt aufgrund von Abhängigkeiten nicht ändern (wenn ich die Abhängigkeiten ändern muss, aber versuche, dies zu vermeiden).

Gibt es einen Weg, dies zu erreichen, oder ist es Wunschdenken?

+0

so, 'MungedFormatForAnotherSystem' sollte nicht serialisiert und in irgendeiner Weise in Elasticsearch gespeichert werden? –

+0

Richtig, es muss unter dem gleichen Namen gespeichert werden, aber als Datum, nicht als geschachteltes Objekt. – Martin

Antwort

0

Sie können mit einem benutzerdefinierten dies tun Json.Net JsonConverter

void Main() 
{ 
    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<ESClass>(mm => mm 
       .AutoMap() 
       .Properties(p => p 
        // map the type as a "date" field type 
        .Date(t => t 
         .Name(n => n.LastUpdatedDate) 
        ) 
       ) 
      ) 
     ) 
    ); 

    client.IndexMany(new[] { 
     new ESClass { Id = "1", LastUpdatedDate = new MyDate { Original = DateTime.UtcNow.Date } }, 
     new ESClass { Id = "2", LastUpdatedDate = new MyDate() }, 
     new ESClass { Id = "3" } 
    }); 

    client.Refresh(defaultIndex); 

    // returns document with Id "1" 
    client.Search<ESClass>(s => s 
     .Query(q => +q 
      .Term(f => f.LastUpdatedDate, DateTime.UtcNow.Date) 
     ) 
    ); 
} 

public class ESClass 
{ 
    public string Id { get; set; } 
    public MyDate LastUpdatedDate { get; set; } 
} 

[JsonConverter(typeof(MyDateConverter))] 
public class MyDate 
{ 
    public DateTime Original { get; set; } 
    public string MungedFormatForAnotherSystem { get; set; } 
} 

public class MyDateConverter : JsonConverter 
{ 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     var v = (MyDate)value; 
     writer.WriteValue(v.Original); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     switch (reader.TokenType) 
     { 
      case JsonToken.Date: 
       return new MyDate { Original = (DateTime)reader.Value }; 
      default: 
       throw new JsonSerializationException($"Cannot deserialize {reader.TokenType} to {typeof(MyDate).FullName}"); 
     } 
    } 

    public override bool CanConvert(Type objectType) => typeof(MyDate).IsAssignableFrom(objectType); 
} 
+0

Wow, sehr gründlich. Gibt es eine Möglichkeit, das zu tun, ohne das Attribut hinzuzufügen? Wie in Anwendung auf den Kunden direkt? – Martin

+0

Ja, Sie können den Converter für 'MyDate' Typen zum Serializer hinzufügen. Leiten Sie 'JsonNetSerializer' ab, überschreiben Sie' ContractConverter' und geben Sie eine Instanz des Konverters zurück, wenn der Typ übereinstimmt. Siehe http://stackoverflow.com/a/37204337/1831 –

Verwandte Themen