[英]MongoDB C# Driver - how to enforce projection on the joined collection in .NET?
Here's the code:这是代码:
ProjectionDefinition<Accountant> projDefAccountant = Builders<Accountant>.Projection
.Include(x => x.Id)
.Include(x => x.Name);
ProjectionDefinition<Client> projDefClient = Builders<Client>.Projection
.Include(c => c.Name)
.Include(c => c.Address)
.Include(c => c.Occupation);
IMongoCollection<Accountant> collection = mongoDatabase.GetCollection<Accountant>("accountants");
IMongoCollection<Client> foreignCollection = mongoDatabase.GetCollection<Client>("clients");
var results = collection.Aggregate()
.Project<Accountant>(projDefAccountant)
.Lookup<Accountant, Client, Accountant>(
foreignCollection: foreignCollection,
localField: ac => ac.BestClientsIds,
foreignField: c => c.Id,
@as: ac => ac.MyClients
).ToList().AsQueryable();
I'm able to use the first projection "projDefAccountant"
to limit what fields I want out of the "accountants"
collection.我可以使用第一个投影
"projDefAccountant"
来限制我想要从"accountants"
集合中删除哪些字段。 Is there a way to enforce the "projDefClient"
projection on the joined "clients"
collection so that the join doesn't return all the fields but only those specified in the "projDefClient"
?有没有办法在加入的
"clients"
集合上强制执行"projDefClient"
投影,以便加入不会返回所有字段,而只返回"projDefClient"
指定的字段? Thx.谢谢。
You can use $lookup with custom pipeline and your aggregation could look like this:您可以将$lookup 与自定义管道一起使用,您的聚合可能如下所示:
db.accountants.aggregate([
{ "$project" : { "_id" : 1, "Name" : 1, BestClientsIds: 1 } },
{
"$lookup" : {
"from" : "clients",
"let" : { "best_client_ids" : "$BestClientsIds" },
"pipeline" : [
{ "$match" : { "$expr" : { "$in" : [ "$_id", "$$best_client_ids"] } } },
{ "$project": { Name: 1, Address: 1, Occupation: 1} }
],
as: "MyClients"}
}
]);
In C# there's one overloaded version of .Lookup
which allows you to run that method in an almost strongly-typed way.在 C# 中有一个
.Lookup
的重载版本,它允许您以几乎强类型的方式运行该方法。 Here's the signature:这是签名:
IAggregateFluent<TNewResult> Lookup<TForeignDocument, TAsElement, TAs, TNewResult>(
IMongoCollection<TForeignDocument> foreignCollection,
BsonDocument let,
PipelineDefinition<TForeignDocument, TAsElement> lookupPipeline,
FieldDefinition<TNewResult, TAs> @as,
AggregateLookupOptions<TForeignDocument, TNewResult> options = null)
where TAs : IEnumerable<TAsElement>;
You can modify projDefAccountant
so that it includes BestClientsIds
field:您可以修改
projDefAccountant
以使其包含BestClientsIds
字段:
ProjectionDefinition<Accountant> projDefAccountant = Builders<Accountant>.Projection
.Include(x => x.Id)
.Include(x => x.Name)
.Include(x => x.BestClientsIds);
Then it's easier to specify let
and $match
phases as BsonDocument
however the rest stays strongly-typed:然后将
let
和$match
阶段指定为BsonDocument
更容易,但其余部分保持强类型:
var filter = new BsonDocumentFilterDefinition<Client>(BsonDocument.Parse("{ $expr: { $in: [ '$_id', '$$ids' ] } }"));
PipelineDefinition< Client, Client> pipeline = new PipelineStagePipelineDefinition<Client, Client>(
new IPipelineStageDefinition[]
{
PipelineStageDefinitionBuilder.Match(filter),
PipelineStageDefinitionBuilder.Project<Client, Client>(projDefClient),
});
ExpressionFieldDefinition<Accountant, Client[]> fieldDef
= new ExpressionFieldDefinition<Accountant, Client[]>(f => f.MyClients);
var letDef = BsonDocument.Parse("{ ids: '$BestClientsIds' }");
var results = collection.Aggregate()
.Project<Accountant>(projDefAccountant)
.Lookup<Client, Client, Client[], Accountant>(
foreignCollection: foreignCollection,
let: letDef,
lookupPipeline: pipeline,
@as: fieldDef
).ToList().AsQueryable();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.