Вы можете использовать $ 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"}
}
]);
Пн go Детская площадка
В C# есть одна перегруженная версия .Lookup
, которая позволяет вам запускать этот метод почти строго типизированным способом. Вот подпись:
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>;
Вы можете изменить projDefAccountant
так, чтобы он включал поле BestClientsIds
:
ProjectionDefinition<Accountant> projDefAccountant = Builders<Accountant>.Projection
.Include(x => x.Id)
.Include(x => x.Name)
.Include(x => x.BestClientsIds);
Тогда будет проще указать фазы 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();