C# MongoDB LINQ连接集合属性类型的属性

C# MongoDB LINQ连接集合属性类型的属性,c#,mongodb,linq,mongodb-.net-driver,C#,Mongodb,Linq,Mongodb .net Driver,我有以下类,它们通过MongoDb持久化: public class TypeA { public string Name { get; set; } public List<TypeB> Children { get; set; } } public class TypeB { public string Colour { get; set; } } 我加入了两个TypeA系列,如下所示: IQueryable<TypeA> collecti

我有以下类,它们通过MongoDb持久化:

public class TypeA
{
    public string Name { get; set; }
    public List<TypeB> Children { get; set; }
}

public class TypeB
{
    public string Colour { get; set; }
}
我加入了两个TypeA系列,如下所示:

IQueryable<TypeA> collection1 = GetCollection();
IQueryable<TypeA> collection2 = GetCollection();

var query = from a in collection1
            join b in collection2
                on a.Name equals b.Name
            select new { a.Name };

var list = query.ToList();
var letDef = BsonDocument.Parse("{ colA_Children: '$Children' }");

var filter = new BsonDocumentFilterDefinition<TypeA>(BsonDocument.Parse("{ $expr: { $setEquals: [ '$$colA_Children', '$Children' ] } }"));

var pipeline = new PipelineStagePipelineDefinition<TypeA, TypeA>(
    new IPipelineStageDefinition[]
    {
        PipelineStageDefinitionBuilder.Match(filter),
    });

var fieldDef = new ExpressionFieldDefinition<AggResult, List<TypeA>>(f => f.Matched);

var results = col1.Aggregate()
    .Lookup<TypeA, TypeA, List<TypeA>, AggResult>(
        foreignCollection: col2,
        let: letDef,
        lookupPipeline: pipeline,
        @as: fieldDef
    ).ToList();
除了颜色属性的子属性集合之外,我如何做类似的事情

我尝试了以下方法,但MongoDb Linq驱动程序显然不喜欢join子句中的SelectMany语句:

IQueryable<TypeA> collection1 = GetCollection();
IQueryable<TypeA> collection2 = GetCollection();

var query = from a in collection1.SelectMany(a => a.Children)
            join b in collection2.SelectMany(b => b.Children)
                on a.Colour equals b.Colour
            select new { a.Colour };

var list = query.ToList();

LINQ不是此类操作的前进道路,因为驱动程序无法将此类语法转换为MongoDB的聚合框架

您需要使用的管道阶段是,它允许您指定自定义连接条件。在这种情况下,您需要或。您的C代码可以如下所示:

IQueryable<TypeA> collection1 = GetCollection();
IQueryable<TypeA> collection2 = GetCollection();

var query = from a in collection1
            join b in collection2
                on a.Name equals b.Name
            select new { a.Name };

var list = query.ToList();
var letDef = BsonDocument.Parse("{ colA_Children: '$Children' }");

var filter = new BsonDocumentFilterDefinition<TypeA>(BsonDocument.Parse("{ $expr: { $setEquals: [ '$$colA_Children', '$Children' ] } }"));

var pipeline = new PipelineStagePipelineDefinition<TypeA, TypeA>(
    new IPipelineStageDefinition[]
    {
        PipelineStageDefinitionBuilder.Match(filter),
    });

var fieldDef = new ExpressionFieldDefinition<AggResult, List<TypeA>>(f => f.Matched);

var results = col1.Aggregate()
    .Lookup<TypeA, TypeA, List<TypeA>, AggResult>(
        foreignCollection: col2,
        let: letDef,
        lookupPipeline: pipeline,
        @as: fieldDef
    ).ToList();
其中:

[BsonIgnoreExtraElements]
public class AggResult : TypeA
{
    public List<TypeA> Matched { get; set; }
}

col1.Aggregate似乎没有包含0个参数的重载。应该使用哪种重载?为什么Aggressult应该从TypeA继承?@User48591您不需要继承,只需要拥有与TypeA相同的字段和一个连接的实体列表。这里是我正在使用的聚合:我看到重载在MongoCollection上,而不是在IQueryable接口上。为了更好地理解您所写的内容,我还阅读了一些mongodb操作。我看到你给出的过滤器是在集合本身上,而不是在每个子类型的颜色属性上。我希望输出为类型B,即在匹配上child@User48591您可以将其更改为{$expr:{$setEquals:['$$colA_Children.color','$Children.color']}},然后将对字符串列表而不是对象列表执行set运算符,但在您的示例中,它是等效的,因为您只有一个属性。改写:$setEquals同时处理对象和字符串