如何使用Builders对Grandchild进行操作?

问题描述 投票:0回答:1

例如,我有一个父母的集合:

class Parent{
public string ParentKey {get;set;}
public IEnumerable<Child> Children {get;set;}
}

class Child{
public string ChildKey {get;set;}
public IEnumerable<GrandChild> GrandChildren {get;set;}
}

class GrandChild {
public string GrandChildKey {get;set;}
public IEnumerable<GreatGrandChild> GreatGrandChildren {get;set;}
}

class GreatGrandChild {
public string GreatGrandChildKey {get;set;}
public string SomeValue {get;set;}
}

我可以像这样在子级别上进行一些推拉:

var filter = Builders<Parent>.Filter.Eq(p => p.ParentKey, "some-parent-key");
var pushDefinition = Builders<Parent>.Push(p => p.Children, newChild);

但我不知道如何从孙子和更深层次执行任何操作。至少我对可以使用的过滤器有一个想法:

var filter = Builders<Parent>.Filter.And(
Builders<Parent>.Filter.Eq(p => p.ParentKey, "some-parent-key"),
Builders<Parent>.Filter.ElemMatch(p => p.Children,
Builders<Child>.Filter.Eq(c => c.ChildKey, "some-child-key"))
);

更新 我发现我可以使用字符串作为目标字段的路径,但我宁愿使用 Lambda 之类的东西来更轻松地重构:

var pushDefinition = Builders<Parent>.Push("Children.$.GrandChildren", newGrandChild);
c# mongodb
1个回答
0
投票

您应该需要一个嵌套的

.ElemMatch
来访问和比较嵌套元素。

var filter = Builders<Parent>.Filter.And(
    Builders<Parent>.Filter.Eq(p => p.ParentKey, "<parentKey>"),
    Builders<Parent>.Filter.ElemMatch(p => p.Children,
        Builders<Child>.Filter.And(
            Builders<Child>.Filter.Eq(c => c.ChildKey, "<childKey>"),
                Builders<Child>.Filter.ElemMatch(c => c.GrandChildren,
                    Builders<GrandChild>.Filter.Eq(c => c.GrandChildKey, "<grandChildKey>")
                )
        )
    )
);

要将新实例推入嵌套数组(我演示了将元素推入

greatGrandChildren
数组的示例),您需要使用
$[<identifier>]
(位置过滤运算符。

var pushDefinition = Builders<Parent>.Update.Push("children.$[c].grandChildren.$[gc].greatGrandChildren", 
    <new GreatGrandChild instance>);

var result = await _collection.UpdateOneAsync(filter, pushDefinition,
    new UpdateOptions
    {
        ArrayFilters = new[]
        { 
            new BsonDocumentArrayFilterDefinition<BsonDocument>(
                new BsonDocument("c.childKey", childKey)
            ),
            new BsonDocumentArrayFilterDefinition<BsonDocument>(
                new BsonDocument("gc.grandChildKey", grandChildKey)
            ),
        }
    });
© www.soinside.com 2019 - 2024. All rights reserved.