Search code examples
c#mongodbmongodb-querynested-documents

query and project a nested array using the c# Mongodb driver


Hi I am trying to learn how to use mongoDb with the c# driver. I have a collection similar to this:

public class DataSnapshot
{

    [BsonId]
    public ObjectId InternalId { get; set; }
    public Int Id { get; set; }
    public string Identifier1 { get; set; }
    public string Identifier2 { get; set; }
    public List<NestedData> NestedData { get; set; }
}

and

public class NestedData
{

    public DateTime TimeStamp { get; set; }
    public double Info1 { get; set; }
    public double Info2 { get; set; }

}

The nested data could be very large.

I want to query the collection to return a list of all nested data within a date range (ideally joining together data from multiple snapshots, but just one would be a good start)

Im struggling to work out how to filter and project this properly. Ive read examples of how to filter, and how to filter and project, but im struggling to get this working for all these conditions

I am trying to do something like this :

context.DataSnapshot.Find(x => x.Identifier1 == "foo" && x.Identifier2 == "bar" && x.NestedData.Timestamp > DateTime.Now.AddYears(-1)).Project(x => x.NestedData).ToList();

How is the best way to do this?

Thanks


Solution

  • You can use LINQ query:

    var q = from doc in col.AsQueryable()
            where doc.Identifier1 == "foo" && doc.Identifier2 == "bar"
            select doc.NestedData
            into nested
            from nestedDoc in nested
            where nestedDoc.TimeStamp > DateTime.Now.AddYears(-1)
            select nestedDoc;
    
    var results = q.ToList();
    

    which gets translated into following MongoDB aggregation:

    [
        { 
            "$match" : { 
                "Identifier1" : "foo", 
                "Identifier2" : "bar" 
                } 
            }, 
        { 
            "$project" : { 
                "NestedData" : "$NestedData", 
                "_id" : 0 
            } 
        }, 
        { 
            "$unwind" : "$NestedData" 
        }, 
        { 
            "$project" : { 
                "nested" : "$NestedData", 
                "nestedDoc" : "$NestedData", 
                "_id" : 0 
            } 
        }, 
        { 
            "$match" : { 
                "nestedDoc.TimeStamp" : { 
                    "$gt" : ISODate("2019-04-24T23:36:42.519Z") 
                } 
            } 
        }, 
        { 
            "$project" : { 
                "nestedDoc" : "$nestedDoc", 
                "_id" : 0 
            } 
        }
    ]
    

    So entire filtering will be performed in the database.