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