2017-02-05 3 views
0

Ich habe ein Projekt, wo ich eine Reihe von Formen haben:Handhabung Abfragen über zugehörige Dokumente in RavenDB

public class Form 
{ 
    public string Id { get; set; } 
    public string Name { get; set; } 
    public IList<string> FieldValueIds { get; set; } 
    public string UserId { get; set; } // the user who completed the form. 
    public string FormTemplateId { get; set; } 
} 

Welche jeder „implementieren“ eine Formularvorlage bei der Erstellung des Formulars ausgewählt.

public class FormTemplate 
{ 
    public string Id { get; set; } 
    public string Name { get; set; } 
    public IList<string> FieldIds { get; set; } 
} 

Welche definiert Felder in dem Formular vorhanden sind. Jedes Feld

Speichert Informationen über das Feld, z. B. eine Beschreibung und den erwarteten Typ. Jedes FormField kann in mehreren FormTemplates vorhanden sein, wobei die Werte für das Formular als FieldValue-Objekte gespeichert werden, die sich auf das Formular selbst beziehen.

public class FieldValue 
{ 
    public string Id { get; set; } 
    public string FieldId { get; set; } 
    public string ValueAsJsonString { get; set; } 
} 

Weitere Aufgaben umfassen das Benutzerobjekt:

public class User 
{ 
    public string Id { get; set; } 
    public string Username { get; set; } 
    public string GivenNames { get; set; } 
    public string Surname { get; set; } 
} 

Ich mag wäre in der Lage sein, eine Abfrage auszuführen alle Formulare von einem Benutzer abgeschlossen zu finden, mit einem bestimmten Namen, oder alle Formularen in dem ein Feld mit dem Namen X hat den Wert Y und so weiter.

ich in der Verwendung von Indizes ausgesehen haben, wie in der Dokumentation angegeben Indexing related documents, aber die Umsetzung wie in der Dokumentation präsentiert warf einen NotSupportedException wenn ich das Beispiel wie folgt umgesetzt:

class FormTemplates_ByFieldAndName : AbstractIndexCreationTask<FormTemplate> 
{ 
    public class Result 
    { 
     public string Name { get; set; } 
     public IList<string> FieldNames { get; set; } 
    } 

    public FormTemplates_ByFieldAndName() 
    { 
     Map = FormTemplates => from FormTemplate in FormTemplates 
          select new 
          { 
           Name = FormTemplate.Name, 
           FieldNames = FormTemplate.FieldIds.Select(x => LoadDocument<FormField>(x).Name) 
          }; 
    } 
} 

// in code: 
IList<FormTemplate> TestResults = session.Query<FormTemplates_ByFieldAndName.Result, FormTemplates_ByFieldAndName>() 
        .Where(x => x.Name == "TemplateName" || x.FieldNames.Contains("FieldName")) 
        .OfType<FormTemplate>() 
        .ToList(); 

so gut wie ich kann sagen, Dies wurde korrekt implementiert, jedoch habe ich einen Vorschlag gesehen, die .Contains durch eine .Any-Implementierung zu ersetzen. Stattdessen experimentiere ich mit einem anderen Ansatz, indem ich aufeinanderfolgende .Where Argumente anwende. Wie so:

var pre = session.Query<FormTemplates_ByFieldAndName.Result, FormTemplates_ByFieldAndName>(); 
var pr2 = pre.Where(x => x.Name == "TypeTest25"); 

List<FormTemplate> TestResults = pr2 
    .Where(x => x.FieldNames.Any(a => a == "field25")) 
    .OfType<FormTemplate>() 
    .OrderByScoreDescending() 
    .ToList(); 

Ändern des Systems in einer Fabrik orientierten Ansatz zur Durchführung von in einem vorgegebenen Format auf eine alternative Zeichenkette aufeinanderfolgende Filter auf Basis der Anwendung.

Soll ich so für diese Implementierung gehen und wenn nicht, was sollte ich ändern? Insbesondere, wenn ich mit der Indexierungsoption fortfahren soll, wie würde ich diese Technik auf die verschachtelte Beziehung zwischen Formularen und FormFields über FormTemplates anwenden.

Antwort

0

Sie scheinen zu versuchen, dies auf eine Weise zu tun, die meist relational ist, aber Sie müssen nicht.

Anstatt zu versuchen, eine Reihe von unabhängigen Dokumenten zu haben, die jeweils einen Teil der Daten haben, speichern Sie alles in einem einzigen Dokument.

public class Form 
{ 
    public string Id { get; set; } 
    public string Name { get; set; } 
    public IList<FieldValue> FieldValues { get; set; } 
    public string UserId { get; set; } // the user who completed the form. 
    public string FormTemplateId { get; set; } 
} 

public class FieldValue 
{ 
    public string Id { get; set; } 
    // can store the value directly! 
    //public string ValueAsJsonString { get; set; } 
    public object Value {get; set; } 
} 

Dies wird Dokumente erstellen, die wie folgt aussieht:

{ 
    "Id": "forms/1234", 
    "Name": "Tom", 
    "FieldValues": [ 
    { 
     "Id": "FromValues/SchoolDistrictName", 
     "Value": "ABi195" 
    } 
    ], 
    "UserId": "users/tom", 
    "FormTemplateId": "FromTemplate/1234" 
} 

die eine viel natürlichere Art und Weise, die Dinge zu modellieren.

https://ravendb.net/docs/article-page/3.5/Csharp/indexes/using-dynamic-fields

+0

Oh Dank: An diesem Punkt können Sie RavenDB die Fähigkeit Index dynamische Daten finden Sie in den docs hier nutzen! Ich habe das obige Beispiel bearbeitet, um die Art des Feldwerts genauer widerzuspiegeln.Wäre es möglich, dass mein Index auch die Beziehung zwischen den FormField- und FieldValue-Objekten darstellt? Ich würde gerne in der Lage sein, eine Abfrage zu haben, wo ich in der Lage bin, alle Forms mit einem FormField X mit einem FormValue Y zu finden. Bis jetzt kann ich die eine oder andere nicht diese spezifische Funktionalität tun. –

+0

Ja, das kannst du sicherlich tun. Hier kommen dynamische Felder ins Spiel –

+0

Wie würden Sie eine Lucene-Syntax-Abfrage formatieren, um auf diese dynamischen Felder zuzugreifen? –