Tengo una colección de personas. Estoy tratando de encontrar la persona de mayor edad para cada nombre. Puedo lograr ese resultado usando el comando de consola mongoDB
db.People.aggregate([ { '$sort': { 'Name': 1, 'Age': -1 } }, { '$group': { '_id': '$Name', 'docs': { '$push': '$$ROOT' }, } }, { '$project': { 'top_one': { '$slice': ['$docs', 1] } } } ])
¿Cuál es el equivalente de esto para el controlador C#? Específicamente estoy teniendo problemas con
'docs': { '$push': '$$ROOT' },
Aquí está mi consulta actual de C#:
collection.Aggregate(aggArgs) .SortByDescending(x => x.Age) .Group(x => x.Name, x => new { Name = x.First().Name, FavoriteColor = x.First().FavoriteColor, FavoriteFood = x.First().FavoriteFood }).ToListAsync().Result;
Funciona de manera similar a lo que hace mi comando de consola mongo, pero realmente no me gusta construir un objeto anónimo. Preferiría hacer Group(x => x.Name,x => x.First())
, pero eso genera excepciones de que "First()" no es compatible. Creo que parte del problema es que mi tipo de persona no tiene una identificación, por lo que _id se coloca en el documento mongo real (automáticamente por mongo al insertar). Cuando intenta volver al tipo, no puede hacer un mapeo directo.
Entonces, con las dos versiones de la consulta en mente, ¿cómo recupero mi tipo completo en C# sin tener que deletrear CADA campo?
Es una característica del controlador MongoDB. No acepta First() simple, necesita algo detrás. Eso fue lo que he visto al depurar. Por lo tanto, debe continuar trabajando con First ()... o puede consultar su json directamente:
var result = collection.Aggregate() .Group(new JsonProjectionDefinition<People>(@" { '_id': '$Name', 'docs': { '$push': '$$ROOT' },}")) .Project<TopOne>(new JsonProjectionDefinition<BsonDocument>(@"{ 'top_one': { '$slice': ['$docs', 1] } }")) .ToList();
Maksim me llevó mucho del camino hasta allí. Esto es lo que terminé con el fin de sacar los mismos tipos que estaba poniendo:
collection.Aggregate(aggArgs) .SortByDescending(x => x.Age) .Group(new JsonProjectionDefinition<Person>(@"{ '_id': '$Name', 'docs': { '$push': '$$ROOT'} }")) .Project<BsonDocument>(new JsonProjectionDefinition<BsonDocument>(@"{ 'top': { '$slice': ['$docs', 1] } }")) .Unwind<BsonDocument>(new StringFieldDefinition<BsonDocument>("top")) .ReplaceRoot(new BsonValueAggregateExpressionDefinition<BsonDocument, BsonDocument>(@"$top")) .Project<Person>(new JsonProjectionDefinition<BsonDocument>(@"{ _id: 0 }")) .ToList();