MongoDB LINQ加入集合属性类型的属性

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

我有以下类,这些类通过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();

如何在Color属性的子属性集合上执行类似的操作?

我已经尝试了以下方法,但是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();
c# mongodb linq mongodb-.net-driver
1个回答
1
投票

LINQ并非此类操作的前进之路,因为驱动程序将无法将此类语法转换为MongoDB的Aggregation Framework。

您需要使用的管道阶段是$lookup with custom pipeline,它允许您指定自定义的“加入”条件。在这种情况下,您需要$setEquals$setIsSubset。您的C#代码如下所示:

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; }
}
© www.soinside.com 2019 - 2024. All rights reserved.