2016-04-12 10 views
1

Ich versuche, NEST 2.X und Elastic Search für die dauerhafte Speicherung von Benutzern zu verwenden. Jeder Benutzer enthält eine Liste von Rollen, die ihre Berechtigungen innerhalb unserer Plattform definieren.Verwenden von Interface abgeleiteten Klassen mit NEST und ElasticSearch

Es gibt verschiedene Arten von Rollen jeweils von einem IMediaDetectionRole Schnittstelle ableiten:

public class MediaDetectionUser 
{ 
    public string Username { get; set; } 
    public ICollection<IMediaDetectionRole> Roles { get; set; } 

    public MediaDetectionUser() 
    { 
     Roles = new List<IMediaDetectionRole>(); 
    } 
} 

public interface IMediaDetectionRole 
{ 
    string Name { get; } 
    string GetDescription(); 
    string GetRoleType {get;} 
} 

[ElasticsearchType(Name="MediaDetectionAdminRole")] 
public class MediaDetectionAdminRole : IMediaDetectionRole 
{   
    public string Name { get { return "Admin"; } } 
    public string GetDescription() { return "Admin users can create other users within the account"; } 
    public string GetRoleType { get { return this.GetType().Name; } } 
} 

[ElasticsearchType(Name = "MediaDetectionManagerRole")] 
public class MediaDetectionManagerRole : IMediaDetectionRole 
{ 
    public string Name { get { return "Manager"; } } 
    public string GetDescription() { return "Managers can modify account-level properties"; } 
    public string GetRoleType { get { return this.GetType().Name; } } 
} 

[ElasticsearchType(Name = "MediaDetectionCreatorRole")] 
public class MediaDetectionCreatorRole : IMediaDetectionRole 
{ 
    public string Name { get { return "Creator"; } } 
    public string GetDescription() { return "Creators can create new Media Detection Profiles"; } 
    public string GetRoleType { get { return this.GetType().Name; } } 
} 

ich die Daten in Elasticsearch Lagerung keine Probleme haben, aber wenn ich gehen, um die Daten, die die Daten NEST können abfragen Finde die Art dieser Rollen nicht heraus. Ich bekomme:

Could not create an instance of type IMediaDetectionRole. 
Type is an interface or abstract class and cannot be instantiated. 
Path 'hits.hits[0]._source.roles[0].name', line 1, position 343. 

Was ist der richtige Weg verschachtelt Objektdaten an den richtigen Klassentyp zurück zur Karte?

Vielen Dank!

-Z

+1

Dieser genaue Anwendungsfall wird in der Dokumentation erklärt https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/covariant-search-results.html :) –

+0

Danke Martijn, I Sehen Sie, wie dies für ein Top-Level-Objekt funktionieren würde. Diese Instanzen sind jedoch Teil einer Liste innerhalb des MediaDetectionUser-Objekts. Es ist mir nicht klar, wie ich entweder .Types() oder einen ConcreteTypeSelector verwenden würde, um die Typen eines verschachtelten Objekts aufzulösen. – zorlack

+1

Für Ihre Sammlung innerhalb des DTO können Sie [JsonPropery (ItemTypeHandling = TypeHandling.Objects] verwenden, dies fügt dem serialisierten Ergebnis $ type hinzu und json.net kann es wieder in die richtige Klasse deserialisieren. –

Antwort

1

Okay, so dass ich denke, das ist weniger ein NEST/ES Frage und eine JSON.NET Frage. Offensichtlich besteht die Lösung für dieses Problem darin, JSON.NET anzuweisen, Typhinweise für jedes Mitglied der Liste bereitzustellen.

Per @ MartijnLaarmans Vorschlag Ich habe der Roles-Eigenschaft ein [JsonProperty] -Attribut hinzugefügt. Siehe unten:

public class MediaDetectionUser 
{ 
    public string Username { get; set; } 

    //This JsonProperty helps reference the types during deserialization 
    [JsonProperty("Roles", ItemTypeNameHandling = TypeNameHandling.All)] 
    public ICollection<IMediaDetectionRole> Roles { get; set; } 

    public MediaDetectionUser() 
    { 
     Roles = new List<IMediaDetectionRole>(); 
    } 
} 

Hier ein Beispiel für die JSON ist, wie es in der _Source innen Elasticsearch erscheint:

Roles: [ 
    { 
    $type: "MediaDetectionFrontend.ServiceModel.Types.MediaDetectionAdminRole, MediaDetectionFrontend.ServiceModel", 
    name: "Admin", 
    getRoleType: "MediaDetectionAdminRole" 
    }, 
    { 
    $type: "MediaDetectionFrontend.ServiceModel.Types.MediaDetectionCreatorRole, MediaDetectionFrontend.ServiceModel", 
    name: "Creator", 
    getRoleType: "MediaDetectionCreatorRole" 
    }, 
    { 
    $type: "MediaDetectionFrontend.ServiceModel.Types.MediaDetectionEditorRole, MediaDetectionFrontend.ServiceModel", 
    name: "Editor", 
    getRoleType: "MediaDetectionEditorRole" 
    } 
] 

Sie können sehen, dass die $ type-Attribut jetzt den vollen Typdeskriptor jedes Elements bietet in Die Liste.

Vielen Dank an @MartijnLaarman, der mir geholfen hat, dieses Problem zu lösen, obwohl es wirklich nichts mit ElasticSearch und NEST zu tun hat.

Verwandte Themen