2015-04-18 14 views
6

Ich habe die folgende Struktur:Projektion von mongodb Subdokument mit C# .NET-Treiber 2.0

public class Category 
{ 
    [BsonElement("name")] 
    public string CategoryName { get; set; } 

    [BsonDateTimeOptions] 
    [BsonElement("dateCreated")] 
    public DateTime DateStamp { get; set; } 

    [BsonElement("tasks")]   
    public List<TaskTracker.Task> Task { get; set; } 
} 

public class Task 
{ 
    [BsonElement("name")] 
    public string TaskName { get; set; } 

    [BsonElement("body")] 
    public string TaskBody { get; set; } 
} 

Ich versuche, eine Category abfragen alle TaskName Werte zu erhalten und sie dann in eine Liste zurück angezeigt werden in ein Listenfeld

habe ich versucht, mit dieser Abfrage:

var getTasks = Categories.Find<Category>(x => x.CategoryName == catName) 
         .Project(Builders<Category>.Projection 
                .Include("tasks.name") 
                .Exclude("_id")) 
         .ToListAsync() 
         .Result; 

Aber was bekommen zurückgekehrt ist: {"tasks": [{"name: "test"}]}.

Gibt es sowieso, nur den String-Wert zurückzugeben?

Antwort

10

Wie Avish sagte, müssen Sie die Aggregations-API verwenden, um das resultierende Dokument so aussehen zu lassen, wie Sie es möchten. Der Treiber kann jedoch einige davon für Sie verschwinden lassen, wenn Sie die Ausdrucksbaum-API für das Projekt verwenden, wie Sie es bei der Suche getan haben. Zum Beispiel glaube ich, die folgenden sollte für Sie arbeiten:

var taskNames = await Categores.Find(x => x.CategoryName == catName) 
    .Project(x => x.Tasks.Select(y => y.Name)) 
    .ToListAsync(); 

Dies sollte nur eine zählbare von Strings (tasks.name) für jede Kategorie zurückbringen. Der Fahrer wird diese Projektion prüfen und nur das Feld tasks.name zurückziehen.

+0

Ich habe Ihre Abfrage versucht und habe versucht, es zu einer 'List >' 'aber was wird zurückgegeben wird: '{System.Linq.Enumerable.WhereSelectEnumerableIterator } ' – Lynchy

+0

Ja, das ist konvertierbar zu einem IEnumerable . Könnten Sie etwas mehr Code über das, was Sie tun, zur Verfügung stellen? –

+0

Ich denke, ich habe eine Lösung gefunden. Ich habe die 'taskNames'-Abfrage wie folgt zurückgeliefert:' taskNames [0] .ToList(); 'zurückgeben und das schien alles zu funktionieren. Ist das eine gute Praxis? – Lynchy

4

MongoDB unterstützt Projektionen nicht so wie SQL-Datenbanken; Sie können nach einem Teildokument fragen, aber Sie würden immer noch etwas zurückbekommen, das mit dem Schema des Dokuments übereinstimmt, das Sie abgefragt haben. In Ihrem Fall erhalten Sie nur das Feld tasks und für jede Aufgabe nur das Feld name zurück.

Sie können ganz einfach diese Transformation in eine Liste von Strings Ebene LINQ:

var categoryTasks = Categories.Find<Category>(x => x.CategoryName == catName) 
        .Project(Builders<Category>.Projection 
               .Include("tasks.name") 
               .Exclude("_id")) 
        .ToListAsync() 
        .Result; 

var taskNames = categoryTasks.Tasks.Select(task => task.Name).ToList(); 

Alternativ können Sie mit der Aggregationen API einige ausgefallene Sachen tun (die benutzerdefinierte Projektionen jedoch zwingend nötig, ein bisschen), aber das würde wahrscheinlich für dich übertrieben.

Verwandte Themen