Mongodb C# driver return only matching sub documents in array

前端 未结 1 1259
遥遥无期
遥遥无期 2020-12-07 04:28

I have a document in this format:

{
    _id: ...,
    myArray: [{other: stuff}, {other: stuff}, ...],
    ...
}

I want to find elements tha

相关标签:
1条回答
  • 2020-12-07 05:21

    Typically you need to use $filter in Aggregation Framework to filter nested array. However there's an easier way to achieve that using MongoDB .NET Driver and IQueryable interface.

    Considering simplest model:

    public class MyModel
    {
        public string _id { get; set; }
        public IEnumerable<MyNestedModel> myArray { get; set; }
    }
    
    public class MyNestedModel
    {
        public string other { get; set; }
    }
    

    and following data:

    var m = new MyModel()
    {
        _id = "1",
        myArray = new List<MyNestedModel>() {
            new MyNestedModel() {  other = "stuff" },
            new MyNestedModel() { other = "stuff" },
            new MyNestedModel() { other = "stuff2" } }
    };
    
    Col.InsertOne(m);
    

    you can simply call .AsQueryable() on your collection and then you can write LINQ query which will be translated by MongoDB driver to $filter, try:

    var query = from doc in Col.AsQueryable()
                where doc._id == "1"
                select new MyModel()
                {
                    _id = doc._id,
                    myArray = doc.myArray.Where(x => x.other == "stuff")
                };
    
    var result = query.ToList();
    

    EDIT:

    Alternatively you can write $filter part as a raw string and then use .Aggregate() method. Using this approach you don't have to "map" all properties however the drawback is that you're losing type safety since this is just a string, try:

    var addFields = BsonDocument.Parse("{ \"$addFields\": { myArray: { $filter: { input: \"$myArray\", as: \"m\", cond: { $eq: [ \"$$m.other\", \"stuff\" ] } }  } } }");
    
    var query = Col.Aggregate()
                   .Match(x => x._id == "1")
                   .AppendStage<MyModel>(addFields);
    

    $addFields is used here to overwrite existing field.

    0 讨论(0)
提交回复
热议问题