2015-04-18 15 views
6

Ho la seguente struttura:Proiezione di MongoDB documento secondario utilizzando C conducente # .NET 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; } 
} 

Sto cercando di interrogare un Category per ottenere tutti i valori TaskName e poi tornare a un elenco da visualizzare in una casella di riepilogo.

Ho provato con questa query:

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

Ma che cosa ottenere restituito è: {"tasks": [{"name: "test"}]}.

Esiste comunque la restituzione del valore di stringa?

risposta

10

Come affermato da Avish, è necessario utilizzare l'API di aggregazione per ottenere il documento risultante come desiderato. Tuttavia, il driver può far scomparire alcune di esse se si utilizza l'API della struttura di espressioni per il progetto come è stato fatto per Trova. Per esempio, credo che il seguente dovrebbe funzionare per voi:

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

Questo deve solo riportare un enumerabile di stringhe (tasks.name) per ogni categoria. L'autista controllerà questa proiezione e ritirerà solo il campo tasks.name.

+0

Ho provato la tua query e ho provato ad aggiungerla a un 'Elenco >' ma ciò che viene restituito è: '{System.Linq.Enumerable.WhereSelectEnumerableIterator } ' – Lynchy

+0

Sì, che è convertibile in un oggetto IEnumerable . Potresti fornire altro codice su cosa stai facendo? –

+0

Penso di aver trovato una soluzione. Ho restituito la query 'taskNames' in questo modo:' return taskNames [0] .ToList(); 'e sembrava funzionare. Questa è una buona pratica? – Lynchy

4

MongoDB in realtà non supporta le proiezioni come fanno i database SQL; puoi chiedere un documento parziale, ma dovresti comunque recuperare qualcosa che corrisponde allo schema del documento che stavi interrogando. Nel tuo caso, stai recuperando solo il campo tasks e, per ogni attività, solo il campo name.

Si può facilmente trasformare questo in una lista di stringhe utilizzando LINQ pianura:

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(); 

In alternativa, è possibile fare alcune cose di fantasia con l'API aggregazioni (che supporta le proiezioni personalizzate, kinda), ma che avrebbe probabilmente sarà eccessivo per te.

Problemi correlati