Reputation: 807
In C# using the .NET MongoDB driver, I am trying to retrieve objects that are in a nested array of a document and that match some criteria.
Models:
public class MainElement
{
[BsonId]
public ObjectId DocumentId { get; set; }
public string A { get; set; }
public string B { get; set; }
public List<NestedElement> NestedObjects { get; set; }
}
public class NestedElement
{
public DateTime Date { get; set; }
public string W { get; set; }
public long Y { get; set; }
}
What I want to retrieve is the property A from MainElement and properties Date, W, Y from NestedElement for all documents thats matches my filters.
So far I tried this but it returns the full MainElement document:
var filters = Builders<MainElement>.Filter.Eq("A", "Something") &
Builders<MainElement>.Filter.Eq("B", "AnotherThing") &
Builders<MainElement>.Filter.Gte("NestedObjects.Date", day) &
Builders<MainElement>.Filter.Eq("NestedObjects.W", "ABC") &
Builders<MainElement>.Filter.Gte("NestedObjects.Y", 1500);
var projection = Builders<MainElement>.Projection.Include("A")
.Include("NestedObjects.Date")
.Include("NestedObjects.W")
.Include("NestedObjects.Y");
var elements = Collection.Find(filters).Project(projection).ToList();
Any ideas?
Upvotes: 1
Views: 3615
Reputation: 38880
You should be able to write your query like this:
// We need the NestedElement filter twice: once to filter documents and once to filter the array in the projection
var nestedFilter = Builders<NestedElement>.Filter.Gte(n => n.Date, day)
& Builders<NestedElement>.Filter.Eq(n => n.W, "ABC")
& Builders<NestedElement>.Filter.Eq(n => n.Y, 1500);
var elements = Collection
.Find(
Builders<MainElement>.Filter.Eq(e => e.A, "Something")
& Builders<MainElement>.Filter.Eq(e => e.B, "AnotherThing")
// match only documents that have matching nested array elements
& Builders<MainElement>.Filter.ElemMatch(e => e.NestedObjects, nestedFilter)
)
.Project(
Builders<MainElement>.Projection
.Include(e => e.A)
// include only matching elements in the resulting object
.ElemMatch(e => e.NestedObjects, nestedFilter)
)
.ToList();
I've used ElemMatch
in the document filter because, from your comments, that seems to be what you actually want. For example: one of the many NestedObjects should have Date=day,W=ABC,Y>=1500, rather than one NestedObject matching Date=day, and another on the same document matching W=ABC and Y>=1500.
Upvotes: 3
Reputation: 6629
You have to user $project
and $filter
the array.
This is what I try:mongoplayground
Upvotes: 0