Обикновено трябва да използвате $filter в Aggregation Framework, за да филтрирате вложен масив. Има обаче по-лесен начин да постигнете това с помощта на MongoDB .NET Driver и IQueryable интерфейс.
Като се има предвид най-простият модел:
public class MyModel
{
public string _id { get; set; }
public IEnumerable<MyNestedModel> myArray { get; set; }
}
public class MyNestedModel
{
public string other { get; set; }
}
и следните данни:
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);
можете просто да извикате .AsQueryable()
във вашата колекция и след това можете да напишете LINQ заявка, която ще бъде преведена от MongoDB драйвер в $filter
, опитайте:
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();
РЕДАКТИРАНЕ:
Като алтернатива можете да напишете $filter
част като необработен низ и след това използвайте .Aggregate()
метод. Използвайки този подход, не е нужно да „картографирате“ всички свойства, но недостатъкът е, че губите безопасност на типа, тъй като това е просто низ, опитайте:
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
се използва тук за презаписване на съществуващо поле.