【发布时间】:2016-09-27 11:37:57
【问题描述】:
数据: 集合包含审计记录列表,我想从集合中返回最后修改的项目。
例如:
所以查询只需要返回 Audit 1235 和 1237。
以下语句在 Mongo Shell 中工作并返回亚毫秒级的数据,我只需要弄清楚如何返回整个 Collection 项目而不仅仅是 Id。
db.Forms.aggregate(
{ $group: { _id: "$Id", lastModifiedId: { $last: "$_id" } } }
)
但是,我需要将其转换为 C# 驱动程序的语法。
我目前有以下内容,但它不起作用并返回(由于缺乏更好的术语)奇怪的数据(请参阅声明下的屏幕截图)。
var results = collection.Aggregate()
.Group(new BsonDocument { { "_id", "$Id" }, { "lastModifiedId", new BsonDocument("$last", "_id") } })
.ToListAsync().Result.ToList();
我当前的解决方案取回完整集合,然后通过扩展方法运行它以获取最新记录(其中 list 是完整集合):
var lastModifiedOnlyList =
from listItem in list.OrderByDescending(_ => _.AuditId)
group listItem by listItem.Id into grp
select grp.OrderByDescending(listItem => listItem.AuditId)
.FirstOrDefault();
虽然此代码有效,但由于从集合返回的数据量巨大,它非常慢,因此我需要在列表中进行分组作为集合获取/查找的一部分。
如果我可以提供任何其他信息,请告诉我。
更新:在 Axel 的帮助下,我设法解决了这个问题:
var pipeline = new[] { new BsonDocument { { "$group", new BsonDocument { { "_id", "$Id" }, { "LastAuditId", new BsonDocument { { "$last", "$_id" } } } } } } };
var lastAuditIds = collection.Aggregate<Audit>(pipeline).ToListAsync().Result.ToList().Select(_=>_.LastAuditId);
我将它移到它自己的方法中,然后使用 ID 来取回集合项目,我的投影也可以正常工作:
var forLastAuditIds = ForLastAuditIds(collection);
var limitedList = (
projection != null
? collection.Find(forLastAuditIds & filter, new FindOptions()).Project(projection)
: collection.Find(forLastAuditIds & filter, new FindOptions())
).ToListAsync().Result.ToList();
在这种情况下,“过滤器”是一个表达式或一个 BsonDocument。性能也很棒 - 整个事情都在亚秒级。感谢您的帮助,阿克塞尔!
【问题讨论】: