La domanda non descrive completamente il caso d'uso, quindi ho escogitato alcune potenziali opzioni da esplorare sulla base di alcuni presupposti, in particolare dipendono dalla disponibilità di LINQ e dal targeting di un singolo documento alla volta ( e che probabilmente non vuoi più codice del necessario):
1) Una variazione su quello che hai. Usa un find
standard con una proiezione e un'espressione LINQ.
var projection = Builders<ShapeDocument>.Projection
.Expression(x => x.fooArray.Where(y => y.plot == "circle"));
var items1 = collection
.Find(x => x.user == "Jone Doe")
.Project(projection)
.ToList();
2) Usa la pipeline di aggregazione (potresti usare la stessa proiezione di cui sopra)
var pipeline = collection
.Aggregate()
.Match(x => x.user == "Jone Doe")
.Project(i => new
{
x = i.fooArray.Where(x => x.plot == "circle")
});
var items2 = pipeline.SingleOrDefault();
3) Tirare indietro il documento con tutti gli elementi dell'array, quindi filtrare localmente utilizzando LINQ. Tra i lati positivi, questa è una piccola quantità di codice leggibile, tuttavia, riporta l'intero documento prima del filtraggio. A seconda del tuo uso esatto, questo potrebbe essere accettabile.
var items3 = collection.AsQueryable()
.SingleOrDefault(x => x.user == "Jone Doe")
.fooArray.Where(x => x.plot == "circle");
Se LINQ davvero non è un'opzione, quindi c'è un esempio qui che mostra come potresti convertire la proiezione in non noi LINQ. Totalmente non testato, ma sarebbe qualcosa sulla falsariga di:
var filter = new BsonDocument {
{"input", "$items"},
{"as", "item" },
{"cond", new BsonDocument {
// Fill in the condition values
{ "", new BsonArray { "", xxx } } }
}
};
var project = new BsonDocument {
{ "items", new BsonDocument { { "$filter", filter} } }
};
var pipeline = collection.Aggregate().Project(project);